From 1609a345a52dd47b06d7973ac878d4eecd0e3322 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 3 Aug 2016 18:14:00 +0300 Subject: [PATCH 001/204] crns.py: New attempt to have --unshare option So, here's the enhanced version of the first try. Changes are: 1. The wrapper name is criu-ns instead of crns.py 2. The CLI is absolutely the same as for criu, since the script re-execl-s criu binary. E.g. scripts/criu-ns dump -t 1234 ... just works 3. Caller doesn't need to care about substituting CLI options, instead, the scripts analyzes the command line and a) replaces -t|--tree argument with virtual pid __if__ the target task lives in another pidns b) keeps the current cwd (and root) __if__ switches to another mntns. A limitation applies here -- cwd path should be the same in target ns, no "smart path mapping" is performed. So this script is for now only useful for mntns clones (which is our main goal at the moment). Signed-off-by: Pavel Emelyanov Looks-good-to: Andrey Vagin --- scripts/criu-ns | 240 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 240 insertions(+) create mode 100755 scripts/criu-ns diff --git a/scripts/criu-ns b/scripts/criu-ns new file mode 100755 index 0000000000..e7ebbf0ca2 --- /dev/null +++ b/scripts/criu-ns @@ -0,0 +1,240 @@ +#!/usr/bin/env python +import ctypes +import ctypes.util +import errno +import sys +import os + +# constants for unshare +CLONE_NEWNS = 0x00020000 +CLONE_NEWPID = 0x20000000 + +# - constants for mount +MS_REC = 16384 +MS_PRIVATE = 1 << 18 +MS_SLAVE = 1 << 19 + +# Load libc bindings +_libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) + +try: + _unshare = _libc.unshare +except AttributeError: + raise OSError(errno.EINVAL, "unshare is not supported on this platform") +else: + _unshare.argtypes = [ ctypes.c_int ] + _unshare.restype = ctypes.c_int + +try: + _setns = _libc.setns +except AttributeError: + raise OSError(errno.EINVAL, "setns is not supported on this platform") +else: + _setns.argtypes = [ ctypes.c_int, ctypes.c_int ] + _setns.restype = ctypes.c_int + +try: + _mount = _libc.mount +except AttributeError: + raise OSError(errno.EINVAL, "mount is not supported on this platform") +else: + _mount.argtypes = [ + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_ulong, + ctypes.c_void_p + ] + _mount.restype = ctypes.c_int + +try: + _umount = _libc.umount +except AttributeError: + raise OSError(errno.EINVAL, "umount is not supported on this platform") +else: + _umount.argtypes = [ctypes.c_char] + _umount.restype = ctypes.c_int + + +def run_criu(): + print sys.argv + os.execlp('criu', *['criu'] + sys.argv[1:]) + + +def wrap_restore(): + # Unshare pid and mount namespaces + if _unshare(CLONE_NEWNS | CLONE_NEWPID) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + (r_pipe, w_pipe) = os.pipe() + + # Spawn the init + if os.fork() == 0: + os.close(r_pipe) + + # Mount new /proc + if _mount(None, "/", None, MS_SLAVE|MS_REC, None) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + if _mount('proc', '/proc', 'proc', 0, None) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + # Spawn CRIU binary + criu_pid = os.fork() + if criu_pid == 0: + run_criu() + raise OSError(errno.ENOENT, "No such command") + + while True: + try: + (pid, status) = os.wait() + if pid == criu_pid: + status = os.WEXITSTATUS(status) + break + except OSError: + status = -251 + break + + os.write(w_pipe, "%d" % status) + os.close(w_pipe) + + if status != 0: + sys.exit(status) + + while True: + try: + os.wait() + except OSError: + break + + sys.exit(0) + + # Wait for CRIU to exit and report the status back + os.close(w_pipe) + status = os.read(r_pipe, 1024) + if not status.isdigit(): + status_i = -252 + else: + status_i = int(status) + + return status_i + + +def get_varg(args): + for i in xrange(1, len(sys.argv)): + if not sys.argv[i] in args: + continue + + if i + 1 >= len(sys.argv): + break + + return (sys.argv[i + 1], i + 1) + + return (None, None) + + + +def set_pidns(tpid, pid_idx): + # Joind pid namespace. Note, that the given pid should + # be changed in -t option, as task lives in different + # pid namespace. + + myns = os.stat('/proc/self/ns/pid').st_ino + + ns_fd = os.open('/proc/%s/ns/pid' % tpid, os.O_RDONLY) + if myns != os.fstat(ns_fd).st_ino: + + for l in open('/proc/%s/status' % tpid): + if not l.startswith('NSpid:'): + continue + + ls = l.split() + if ls[1] != tpid: + raise OSError(errno.ESRCH, 'No such pid') + + print 'Replace pid %s with %s' % (tpid, ls[2]) + sys.argv[pid_idx] = ls[2] + break + else: + raise OSError(errno.ENOENT, 'Cannot find NSpid field in proc') + + if _setns(ns_fd, 0) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + os.close(ns_fd) + + +def set_mntns(tpid): + # Join mount namespace. Trick here too -- check / and . + # will be the same in target mntns. + + myns = os.stat('/proc/self/ns/mnt').st_ino + ns_fd = os.open('/proc/%s/ns/mnt' % tpid, os.O_RDONLY) + if myns != os.fstat(ns_fd).st_ino: + root_st = os.stat('/') + cwd_st = os.stat('.') + cwd_path = os.path.realpath('.') + + if _setns(ns_fd, 0) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + os.chdir(cwd_path) + root_nst = os.stat('/') + cwd_nst = os.stat('.') + + def steq(st, nst): + return (st.st_dev, st.st_ino) == (nst.st_dev, nst.st_ino) + + if not steq(root_st, root_nst): + raise OSError(errno.EXDEV, 'Target ns / is not as current') + if not steq(cwd_st, cwd_nst): + raise OSError(errno.EXDEV, 'Target ns . is not as current') + + + os.close(ns_fd) + + +def wrap_dump(): + (pid, pid_idx) = get_varg(('-t', '--tree')) + if pid is None: + raise OSError(errno.EINVAL, 'No --tree option given') + + set_pidns(pid, pid_idx) + set_mntns(pid) + + # Spawn CRIU binary + criu_pid = os.fork() + if criu_pid == 0: + run_criu() + raise OSError(errno.ENOENT, "No such command") + + # Wait for CRIU to exit and report the status back + while True: + try: + (pid, status) = os.wait() + if pid == criu_pid: + status = os.WEXITSTATUS(status) + break + except OSError: + status = -251 + break + + return status + + +action = sys.argv[1] + +if action == 'restore': + res = wrap_restore() +elif action == 'dump' or action == 'pre-dump': + res = wrap_dump() +else: + print 'Unsupported action %s for nswrap' % action + res = -1 + +sys.exit(res) From ca5c93d38385e507cf02209a97e904cd602a104c Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sun, 23 Sep 2018 15:31:54 +0100 Subject: [PATCH 002/204] python: Replace xrange with range In Py2 `range` returns a list and `xrange` creates a sequence object that evaluates lazily. In Py3 `range` is equivalent to `xrange` in Py2. Signed-off-by: Radostin Stoyanov Signed-off-by: Andrei Vagin --- scripts/criu-ns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index e7ebbf0ca2..0910f2a336 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -124,7 +124,7 @@ def wrap_restore(): def get_varg(args): - for i in xrange(1, len(sys.argv)): + for i in range(1, len(sys.argv)): if not sys.argv[i] in args: continue From 226efaac9ba8564f39b0bed181ffca4ce93890e0 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sun, 7 Apr 2019 20:41:37 +0100 Subject: [PATCH 003/204] criu-ns: Convert to python3 style print() syntax Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 0910f2a336..b6b6a1111b 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -57,7 +57,7 @@ else: def run_criu(): - print sys.argv + print(sys.argv) os.execlp('criu', *['criu'] + sys.argv[1:]) @@ -155,7 +155,7 @@ def set_pidns(tpid, pid_idx): if ls[1] != tpid: raise OSError(errno.ESRCH, 'No such pid') - print 'Replace pid %s with %s' % (tpid, ls[2]) + print('Replace pid {} with {}'.format(tpid, ls[2])) sys.argv[pid_idx] = ls[2] break else: @@ -234,7 +234,7 @@ if action == 'restore': elif action == 'dump' or action == 'pre-dump': res = wrap_dump() else: - print 'Unsupported action %s for nswrap' % action + print('Unsupported action {} for nswrap'.format(action)) res = -1 sys.exit(res) From 3f718972900133bdebdacde99646b30363708c1d Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sun, 7 Apr 2019 20:43:12 +0100 Subject: [PATCH 004/204] criu-ns: Print usage info when no args provided Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/criu-ns b/scripts/criu-ns index b6b6a1111b..b582f75800 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -227,6 +227,18 @@ def wrap_dump(): return status +if len(sys.argv) == 1: + print(""" +Usage: + {0} dump|pre-dump -t PID [] + {0} restore [] +\nCommands: + dump checkpoint a process/tree identified by pid + pre-dump pre-dump task(s) minimizing their frozen time + restore restore a process/tree +""".format(sys.argv[0])) + exit(1) + action = sys.argv[1] if action == 'restore': From bfb051a51c31556092a1512fdb88c6807f4e61b1 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sun, 7 Apr 2019 20:55:32 +0100 Subject: [PATCH 005/204] criu-ns: Convert c_char_p strings to bytes object class ctypes.c_char_p Represents the C char * datatype when it points to a zero- terminated string. For a general character pointer that may also point to binary data, POINTER(c_char) must be used. The constructor accepts an integer address, or a bytes object. https://docs.python.org/3/library/ctypes.html#ctypes.c_char_p Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index b582f75800..e065c59716 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -74,11 +74,11 @@ def wrap_restore(): os.close(r_pipe) # Mount new /proc - if _mount(None, "/", None, MS_SLAVE|MS_REC, None) != 0: + if _mount(None, b"/", None, MS_SLAVE|MS_REC, None) != 0: _errno = ctypes.get_errno() raise OSError(_errno, errno.errorcode[_errno]) - if _mount('proc', '/proc', 'proc', 0, None) != 0: + if _mount(b'proc', b'/proc', b'proc', 0, None) != 0: _errno = ctypes.get_errno() raise OSError(_errno, errno.errorcode[_errno]) @@ -98,7 +98,7 @@ def wrap_restore(): status = -251 break - os.write(w_pipe, "%d" % status) + os.write(w_pipe, b"%d" % status) os.close(w_pipe) if status != 0: From 532944695f9760af18bdeb36a1beb7da340cb98c Mon Sep 17 00:00:00 2001 From: prakritigoyal19 Date: Sun, 7 Jun 2020 09:22:53 +0530 Subject: [PATCH 006/204] Add flog to CRIU Change made through this commit: - Include copy of flog as a seperate tree. - Modify the makefile to add and compile flog code. Signed-off-by: prakritigoyal19 --- Makefile | 12 ++- flog/Makefile | 29 ++++++ flog/built-in.S | 4 + flog/include/compiler.h | 71 +++++++++++++ flog/include/flog.h | 9 ++ flog/include/log.h | 17 ++++ flog/include/types.h | 16 +++ flog/include/uapi/flog.h | 149 +++++++++++++++++++++++++++ flog/include/util.h | 37 +++++++ flog/src/Makefile | 5 + flog/src/flog.c | 215 +++++++++++++++++++++++++++++++++++++++ flog/src/main.c | 170 +++++++++++++++++++++++++++++++ flog/tests/test00 | 22 ++++ 13 files changed, 755 insertions(+), 1 deletion(-) create mode 100644 flog/Makefile create mode 100644 flog/built-in.S create mode 100644 flog/include/compiler.h create mode 100644 flog/include/flog.h create mode 100644 flog/include/log.h create mode 100644 flog/include/types.h create mode 100644 flog/include/uapi/flog.h create mode 100644 flog/include/util.h create mode 100644 flog/src/Makefile create mode 100644 flog/src/flog.c create mode 100644 flog/src/main.c create mode 100755 flog/tests/test00 diff --git a/Makefile b/Makefile index c33494bec8..d1f910960d 100644 --- a/Makefile +++ b/Makefile @@ -147,7 +147,7 @@ HOSTCFLAGS += $(WARNINGS) $(DEFINES) -iquote include/ export AFLAGS CFLAGS USERCLFAGS HOSTCFLAGS # Default target -all: criu lib crit +all: flog criu lib crit .PHONY: all # @@ -233,6 +233,15 @@ soccr/built-in.o: $(CONFIG_HEADER) .FORCE $(SOCCR_A): |soccr/built-in.o criu-deps += $(SOCCR_A) +#flog gets used by criu, build it earlier + +flogMakefile: ; +flog%: + $(Q) $(MAKE) $(build)=flog $@ +flog: + $(Q) $(MAKE) $(build)=flog all +.PHONY: flog + # # CRIU building done in own directory # with slightly different rules so we @@ -271,6 +280,7 @@ lib: crit clean mrproper: $(Q) $(MAKE) $(build)=images $@ + $(Q) $(MAKE) $(build)=flog $@ $(Q) $(MAKE) $(build)=criu $@ $(Q) $(MAKE) $(build)=soccr $@ $(Q) $(MAKE) $(build)=lib $@ diff --git a/flog/Makefile b/flog/Makefile new file mode 100644 index 0000000000..12255af719 --- /dev/null +++ b/flog/Makefile @@ -0,0 +1,29 @@ +OPTS=-ggdb3 -Wall -Werror +export OPTS + +CFLAGS += -iquote include +CFLAGS += -iquote flog/include +CFLAGS += -iquote flog/include/uapi + +include $(__nmk_dir)msg.mk + +$(eval $(call gen-built-in,src)) + +flog: + $(Q) $(MAKE) $(build)=$(obj)/src all +.PHONY: flog + +clean-flog: + $(call msg-gen, $@) + $(Q) $(MAKE) $(build)=$(obj)/src clean + $(Q) $(RM) built-in.o +.PHONY: clean-flog + +clean: clean-flog +mrproper: clean + +test: + ./tests/test00 + +all-y += flog + diff --git a/flog/built-in.S b/flog/built-in.S new file mode 100644 index 0000000000..26627d0544 --- /dev/null +++ b/flog/built-in.S @@ -0,0 +1,4 @@ +SECTIONS +{ + .rodata : { _rodata_start = . ; *(.rodata*) ; _rodata_end = . ;} +} diff --git a/flog/include/compiler.h b/flog/include/compiler.h new file mode 100644 index 0000000000..3e56eb0e64 --- /dev/null +++ b/flog/include/compiler.h @@ -0,0 +1,71 @@ +#ifndef __COMPILER_H__ +#define __COMPILER_H__ + +/* + * Various definitions for success build, + * picked from various places, mostly from + * the linux kernel. + */ + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2*!!(condition)])) + +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + +#define NORETURN __attribute__((__noreturn__)) +#define __packed __attribute__((__packed__)) +#define __used __attribute__((__used__)) +#define __maybe_unused __attribute__((unused)) +#define __always_unused __attribute__((unused)) + +#define __section(S) __attribute__ ((__section__(#S))) + +#ifndef __always_inline +# define __always_inline inline __attribute__((always_inline)) +#endif + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#ifndef always_inline +# define always_inline __always_inline +#endif + +#ifndef noinline +# define noinline __attribute__((noinline)) +#endif + +#define __aligned(x) __attribute__((aligned(x))) + +#ifndef offsetof +# define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define barrier() asm volatile("" ::: "memory") + +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define __round_mask(x, y) ((__typeof__(x))((y) - 1)) +#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1) +#define round_down(x, y) ((x) & ~__round_mask(x, y)) +#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) +#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) + +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +#define max(x, y) ({ \ + typeof(x) _max1 = (x); \ + typeof(y) _max2 = (y); \ + (void) (&_max1 == &_max2); \ + _max1 > _max2 ? _max1 : _max2; }) + +#define is_log2(v) (((v) & ((v) - 1)) == 0) + +#endif /* __COMPILER_H__ */ diff --git a/flog/include/flog.h b/flog/include/flog.h new file mode 100644 index 0000000000..f00c20541f --- /dev/null +++ b/flog/include/flog.h @@ -0,0 +1,9 @@ +#ifndef __FLOG_H__ +#define __FLOG_H__ + +#include +#include + +#include "uapi/flog.h" + +#endif /* __FLOG_H__ */ diff --git a/flog/include/log.h b/flog/include/log.h new file mode 100644 index 0000000000..1a165ea9fb --- /dev/null +++ b/flog/include/log.h @@ -0,0 +1,17 @@ +#ifndef __LOG_H__ +#define __LOG_H__ + +#include + +#define pr_out(fmt, ...) fprintf(stdout, fmt, ##__VA_ARGS__) + +#if 1 +# define pr_debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__) +#else +# define pr_debug(fmt, ...) +#endif + +#define pr_err(fmt, ...) fprintf(stderr, "Error (%s:%d): "fmt, __FILE__, __LINE__, ##__VA_ARGS__) +#define pr_perror(fmt, ...) fprintf(stderr, "Error (%s:%d): "fmt "%m\n", __FILE__, __LINE__, ##__VA_ARGS__) + +#endif /* __LOG_H__ */ diff --git a/flog/include/types.h b/flog/include/types.h new file mode 100644 index 0000000000..0e15bfbff5 --- /dev/null +++ b/flog/include/types.h @@ -0,0 +1,16 @@ +#ifndef __FLOG_TYPES_H__ +#define __FLOG_TYPES_H__ + +#include +#include + +typedef uint64_t u64; +typedef int64_t s64; +typedef uint32_t u32; +typedef int32_t s32; +typedef uint16_t u16; +typedef int16_t s16; +typedef uint8_t u8; +typedef int8_t s8; + +#endif /* __FLOG_TYPES_H__ */ diff --git a/flog/include/uapi/flog.h b/flog/include/uapi/flog.h new file mode 100644 index 0000000000..2d879110fc --- /dev/null +++ b/flog/include/uapi/flog.h @@ -0,0 +1,149 @@ +#ifndef __UAPI_FLOG_H__ +#define __UAPI_FLOG_H__ + +#include +#include +#include + +/* + * We work with up to 32 arguments in macros here. + * If more provided -- behaviour is undefined. + */ + +/* + * By Laurent Deniau at https://groups.google.com/forum/#!topic/comp.std.c/d-6Mj5Lko_s + */ +#define FLOG_PP_NARG_(...) FLOG_PP_ARG_N(__VA_ARGS__) +#define FLOG_PP_NARG(...) FLOG_PP_NARG_(1, ##__VA_ARGS__, FLOG_PP_RSEQ_N()) + +#define FLOG_PP_ARG_N( _0, _1, _2, _3, _4, \ + _5, _6, _7, _8, _9, \ + _10,_11,_12,_13,_14, \ + _15,_16,_17,_18,_19, \ + _20,_21,_22,_23,_24, \ + _25,_26,_27,_28,_29, \ + _30,_31, N, ...) N + +#define FLOG_PP_RSEQ_N() \ + 31, 30, 29, 28, 27, \ + 26, 25, 24, 23, 22, \ + 21, 20, 19, 18, 17, \ + 16, 15, 14, 13, 12, \ + 11, 10, 9, 8, 7, \ + 6, 5, 4, 3, 2, \ + 1, 0 + +#define FLOG_GENMASK_0(N, x) 0 +#define FLOG_GENMASK_1(N, op, x, ...) (op(N, 0, x)) +#define FLOG_GENMASK_2(N, op, x, ...) ((op(N, 1, x)) | FLOG_GENMASK_1(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_3(N, op, x, ...) ((op(N, 2, x)) | FLOG_GENMASK_2(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_4(N, op, x, ...) ((op(N, 3, x)) | FLOG_GENMASK_3(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_5(N, op, x, ...) ((op(N, 4, x)) | FLOG_GENMASK_4(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_6(N, op, x, ...) ((op(N, 5, x)) | FLOG_GENMASK_5(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_7(N, op, x, ...) ((op(N, 6, x)) | FLOG_GENMASK_6(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_8(N, op, x, ...) ((op(N, 7, x)) | FLOG_GENMASK_7(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_9(N, op, x, ...) ((op(N, 8, x)) | FLOG_GENMASK_8(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_10(N, op, x, ...) ((op(N, 9, x)) | FLOG_GENMASK_9(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_11(N, op, x, ...) ((op(N, 10, x)) | FLOG_GENMASK_10(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_12(N, op, x, ...) ((op(N, 11, x)) | FLOG_GENMASK_11(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_13(N, op, x, ...) ((op(N, 12, x)) | FLOG_GENMASK_12(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_14(N, op, x, ...) ((op(N, 13, x)) | FLOG_GENMASK_13(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_15(N, op, x, ...) ((op(N, 14, x)) | FLOG_GENMASK_14(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_16(N, op, x, ...) ((op(N, 15, x)) | FLOG_GENMASK_15(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_17(N, op, x, ...) ((op(N, 16, x)) | FLOG_GENMASK_16(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_18(N, op, x, ...) ((op(N, 17, x)) | FLOG_GENMASK_17(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_19(N, op, x, ...) ((op(N, 18, x)) | FLOG_GENMASK_18(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_20(N, op, x, ...) ((op(N, 19, x)) | FLOG_GENMASK_19(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_21(N, op, x, ...) ((op(N, 20, x)) | FLOG_GENMASK_20(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_22(N, op, x, ...) ((op(N, 21, x)) | FLOG_GENMASK_21(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_23(N, op, x, ...) ((op(N, 22, x)) | FLOG_GENMASK_22(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_24(N, op, x, ...) ((op(N, 23, x)) | FLOG_GENMASK_23(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_25(N, op, x, ...) ((op(N, 24, x)) | FLOG_GENMASK_24(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_26(N, op, x, ...) ((op(N, 25, x)) | FLOG_GENMASK_25(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_27(N, op, x, ...) ((op(N, 26, x)) | FLOG_GENMASK_26(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_28(N, op, x, ...) ((op(N, 27, x)) | FLOG_GENMASK_27(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_29(N, op, x, ...) ((op(N, 28, x)) | FLOG_GENMASK_28(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_30(N, op, x, ...) ((op(N, 29, x)) | FLOG_GENMASK_29(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_31(N, op, x, ...) ((op(N, 30, x)) | FLOG_GENMASK_30(N, op, __VA_ARGS__)) +#define FLOG_GENMASK_32(N, op, x, ...) ((op(N, 31, x)) | FLOG_GENMASK_31(N, op, __VA_ARGS__)) + +#define FLOG_CONCAT(arg1, arg2) FLOG_CONCAT1(arg1, arg2) +#define FLOG_CONCAT1(arg1, arg2) FLOG_CONCAT2(arg1, arg2) +#define FLOG_CONCAT2(arg1, arg2) arg1##arg2 + +#define FLOG_GENMASK_(N, op, ...) FLOG_CONCAT(FLOG_GENMASK_, N)(N, op, ##__VA_ARGS__) +#define FLOG_GENMASK(op, ...) FLOG_GENMASK_(FLOG_PP_NARG(__VA_ARGS__), op, ##__VA_ARGS__) + +#define flog_genbit(ord, n, v, ...) \ + _Generic((v), \ + \ + /* Basic types */ \ + char: 0, \ + signed char: 0, \ + unsigned char: 0, \ + signed short int: 0, \ + unsigned short int: 0, \ + signed int: 0, \ + unsigned int: 0, \ + signed long: 0, \ + unsigned long: 0, \ + signed long long: 0, \ + unsigned long long: 0, \ + \ + /* Not used for a while */ \ + /* float: 12, */ \ + /* double: 13, */ \ + /* long double: 14, */ \ + \ + /* Basic poniters */ \ + char *: (1u << (ord - n - 1)), \ + signed char *: (1u << (ord - n - 1)), \ + unsigned char *: (1u << (ord - n - 1)), \ + signed short int *: 0, \ + unsigned short int *: 0, \ + signed int *: 0, \ + unsigned int *: 0, \ + signed long *: 0, \ + unsigned long *: 0, \ + signed long long *: 0, \ + unsigned long long *: 0, \ + void *: 0, \ + \ + /* Const basic pointers */ \ + const char *: (1u << (ord - n - 1)), \ + const signed char *: (1u << (ord - n - 1)), \ + const unsigned char *: (1u << (ord - n - 1)), \ + const signed short int *: 0, \ + const unsigned short int *: 0, \ + const signed int *: 0, \ + const unsigned int *: 0, \ + const signed long *: 0, \ + const unsigned long *: 0, \ + const signed long long *: 0, \ + const unsigned long long *: 0, \ + const void *: 0, \ + \ + /* Systypes and pointers */ \ + default: -1) + +typedef struct { + unsigned int magic; + unsigned int size; + unsigned int nargs; + unsigned int mask; + long fmt; + long args[0]; +} flog_msg_t; + +extern int flog_encode_msg(int fdout, unsigned int nargs, unsigned int mask, const char *format, ...); +void flog_decode_msg(int fdout, const char *format, ...); +extern int flog_decode_all(int fdin, int fdout); + +#define flog_encode(fdout, fmt, ...) \ + flog_encode_msg(fdout, FLOG_PP_NARG(__VA_ARGS__), \ + FLOG_GENMASK(flog_genbit, ##__VA_ARGS__), fmt, ##__VA_ARGS__) + +int flog_map_buf(int fdout); +int flog_close(int fdout); + +#endif /* __UAPI_FLOG_H__ */ diff --git a/flog/include/util.h b/flog/include/util.h new file mode 100644 index 0000000000..17a4d77997 --- /dev/null +++ b/flog/include/util.h @@ -0,0 +1,37 @@ +#ifndef __UTIL_H__ +#define __UTIL_H__ + +#include +#include + +#include "log.h" +#include "types.h" + +#define __xalloc(op, size, ...) \ + ({ \ + void *___p = op(__VA_ARGS__); \ + ___p; \ + }) + +#define xstrdup(str) __xalloc(strdup, strlen(str) + 1, str) +#define xmalloc(size) __xalloc(malloc, size, size) +#define xzalloc(size) __xalloc(calloc, size, 1, size) +#define xrealloc(p, size) __xalloc(realloc, size, p, size) + +#define xfree(p) do { if (p) free(p); } while (0) + +#define xrealloc_safe(pptr, size) \ + ({ \ + int __ret = -ENOMEM; \ + void *new = xrealloc(*pptr, size); \ + if (new) { \ + *pptr = new; \ + __ret = 0; \ + } \ + __ret; \ + }) + +#define memzero_p(p) memset(p, 0, sizeof(*p)) +#define memzero(p, size) memset(p, 0, size) + +#endif /* __UTIL_H__ */ diff --git a/flog/src/Makefile b/flog/src/Makefile new file mode 100644 index 0000000000..ee73ea7252 --- /dev/null +++ b/flog/src/Makefile @@ -0,0 +1,5 @@ +ccflags-y += -DCONFIG_X86_64 -iquote ./include $(OPTS) +ldflags-y += -r + +#obj-y += main.o +obj-y += flog.o diff --git a/flog/src/flog.c b/flog/src/flog.c new file mode 100644 index 0000000000..533625de61 --- /dev/null +++ b/flog/src/flog.c @@ -0,0 +1,215 @@ +#include +#include +#include +#include +#include +#include +#include + +//#include + +#include "uapi/flog.h" +#include "util.h" + +#define MAGIC 0xABCDABCD + +#define BUF_SIZE (1<<20) +static char _mbuf[BUF_SIZE]; +static char *mbuf = _mbuf; +static char *fbuf; +static uint64_t fsize; +static uint64_t mbuf_size = sizeof(_mbuf); + +/*int flog_decode_all(int fdin, int fdout) +{ + flog_msg_t *m = (void *)mbuf; + ffi_type *args[34] = { + [0] = &ffi_type_sint, + [1] = &ffi_type_pointer, + [2 ... 33] = &ffi_type_slong + }; + void *values[34]; + ffi_cif cif; + ffi_arg rc; + size_t i, ret; + char *fmt; + + values[0] = (void *)&fdout; + + while (1) { + ret = read(fdin, mbuf, sizeof(m)); + if (ret == 0) + break; + if (ret < 0) { + fprintf(stderr, "Unable to read a message: %m"); + return -1; + } + if (m->magic != MAGIC) { + fprintf(stderr, "The log file was not properly closed\n"); + break; + } + ret = m->size - sizeof(m); + if (m->size > mbuf_size) { + fprintf(stderr, "The buffer is too small"); + return -1; + } + if (read(fdin, mbuf + sizeof(m), ret) != ret) { + fprintf(stderr, "Unable to read a message: %m"); + return -1; + } + + fmt = mbuf + m->fmt; + values[1] = &fmt; + + for (i = 0; i < m->nargs; i++) { + values[i + 2] = (void *)&m->args[i]; + if (m->mask & (1u << i)) { + m->args[i] = (long)(mbuf + m->args[i]); + } + } + + if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, m->nargs + 2, + &ffi_type_sint, args) == FFI_OK) + ffi_call(&cif, FFI_FN(dprintf), &rc, values); + } + return 0; +}*/ + +static int flog_enqueue(flog_msg_t *m) +{ + if (write(1, m, m->size) != m->size) { + fprintf(stderr, "Unable to write a message\n"); + return -1; + } + return 0; +} + +/*extern char *rodata_start; +extern char *rodata_end; +*/ +/* Pre-allocate a buffer in a file and map it into memory. */ +int flog_map_buf(int fdout) +{ + uint64_t off = 0; + void *addr; + + /* + * Two buffers are mmaped into memory. A new one is mapped when a first + * one is completly filled. + */ + if (fbuf && (mbuf - fbuf < BUF_SIZE)) + return 0; + + if (fbuf) { + if (munmap(fbuf, BUF_SIZE * 2)) { + fprintf(stderr, "Unable to unmap a buffer: %m"); + return -1; + } + off = mbuf - fbuf - BUF_SIZE; + fbuf = NULL; + } + + if (fsize == 0) + fsize += BUF_SIZE; + fsize += BUF_SIZE; + + if (ftruncate(fdout, fsize)) { + fprintf(stderr, "Unable to truncate a file: %m"); + return -1; + } + + if (!fbuf) + addr = mmap(NULL, BUF_SIZE * 2, PROT_WRITE | PROT_READ, + MAP_FILE | MAP_SHARED, fdout, fsize - 2 * BUF_SIZE); + else + addr = mremap(fbuf + BUF_SIZE, BUF_SIZE, + BUF_SIZE * 2, MREMAP_FIXED, fbuf); + if (addr == MAP_FAILED) { + fprintf(stderr, "Unable to map a buffer: %m"); + return -1; + } + + fbuf = addr; + mbuf = fbuf + off; + mbuf_size = 2 * BUF_SIZE; + + return 0; +} + +int flog_close(int fdout) +{ + if (mbuf == _mbuf) + return 0; + + munmap(fbuf, BUF_SIZE * 2); + + if (ftruncate(fdout, fsize - 2 * BUF_SIZE + mbuf - fbuf)) { + fprintf(stderr, "Unable to truncate a file: %m"); + return -1; + } + return 0; +} + +int flog_encode_msg(int fdout, unsigned int nargs, unsigned int mask, const char *format, ...) +{ + flog_msg_t *m; + va_list argptr; + char *str_start, *p; + size_t i; + + if (mbuf != _mbuf && flog_map_buf(fdout)) + return -1; + + m = (void *) mbuf; + + m->nargs = nargs; + m->mask = mask; + + str_start = (void *)m->args + sizeof(m->args[0]) * nargs; + p = memccpy(str_start, format, 0, mbuf_size - (str_start - mbuf)); + if (p == NULL) { + fprintf(stderr, "No memory for string argument\n"); + return -1; + } + m->fmt = str_start - mbuf; + str_start = p; + + va_start(argptr, format); + for (i = 0; i < nargs; i++) { + m->args[i] = (long)va_arg(argptr, long); + /* + * If we got a string, we should either + * reference it when in rodata, or make + * a copy (FIXME implement rodata refs). + */ + if (mask & (1u << i)) { + p = memccpy(str_start, (void *)m->args[i], 0, mbuf_size - (str_start - mbuf)); + if (p == NULL) { + fprintf(stderr, "No memory for string argument\n"); + return -1; + } + m->args[i] = str_start - mbuf; + str_start = p; + } + } + va_end(argptr); + m->size = str_start - mbuf; + + /* + * A magic is required to know where we stop writing into a log file, + * if it was not properly closed. The file is mapped into memory, so a + * space in the file is allocated in advance and at the end it can have + * some unused tail. + */ + m->magic = MAGIC; + + m->size = roundup(m->size, 8); + if (mbuf == _mbuf) { + if (flog_enqueue(m)) + return -1; + } else { + mbuf += m->size; + mbuf_size -= m->size; + } + return 0; +} diff --git a/flog/src/main.c b/flog/src/main.c new file mode 100644 index 0000000000..c84e774781 --- /dev/null +++ b/flog/src/main.c @@ -0,0 +1,170 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "flog.h" + +extern char _rodata_start, _rodata_end; +char *rodata_start = &_rodata_start; +char *rodata_end = &_rodata_end; + +enum { + MODE_BINARY, + MODE_FPRINTF, + MODE_SPRINTF, + MODE_DPRINTF, +}; + +int main(int argc, char *argv[]) +{ + static const char str1[] = "String1 String1"; + static const char str2[] = "string2 string2 string2"; + int fdout = STDOUT_FILENO; + bool use_decoder = false; + int mode = MODE_BINARY; + size_t niter = 100; + int opt, idx; + size_t i; + + static const char short_opts[] = "m:o:di:h"; + static struct option long_opts[] = { + { "mode", required_argument, 0, 'm' }, + { "output", required_argument, 0, 'o' }, + { "decode", no_argument, 0, 'd' }, + { "iter", required_argument, 0, 'i' }, + { "help", no_argument, 0, 'h' }, + { }, + }; + + while (1) { + idx = -1; + opt = getopt_long(argc, argv, short_opts, long_opts, &idx); + if (opt == -1) + break; + + switch (opt) { + case 'm': + if (strcmp(optarg, "binary") == 0) { + mode = MODE_BINARY; + } else if (strcmp(optarg, "fprintf") == 0) { + mode = MODE_FPRINTF; + } else if (strcmp(optarg, "sprintf") == 0) { + mode = MODE_SPRINTF; + } else if (strcmp(optarg, "dprintf") == 0) { + mode = MODE_DPRINTF; + } else + goto usage; + break; + case 'o': + if (strcmp(optarg, "stdout") == 0) { + fdout = fileno(stdout); + } else if (strcmp(optarg, "stderr") == 0) { + fdout = fileno(stderr); + } else { + fdout = open(optarg, O_RDWR | O_CREAT | O_TRUNC, 0644); + if (fdout < 0) { + fprintf(stderr, "Can't open %s: %s\n", + optarg, strerror(errno)); + exit(1); + } + } + break; + case 'i': + niter = atoi(optarg); + break; + case 'd': + use_decoder = true; + break; + case 'h': + default: + goto usage; + } + } + + switch (mode) { + case MODE_BINARY: + if (use_decoder) + return flog_decode_all(STDIN_FILENO, fdout); + + if (fdout != STDOUT_FILENO && flog_map_buf(fdout)) + return 1; + for (i = 0; i < niter; i++) + if (flog_encode(fdout, "Some message %s %s %c %li %d %lu\n", + str1, str2, 'c', (long)-4, (short)2, + (unsigned long)2)) + return 1; + if (flog_close(fdout)) + return 1; + break; + case MODE_DPRINTF: + { + for (i = 0; i < niter; i++) { + dprintf(fdout, "Some message %s %s %c %li %d %lu\n", + str1, str2, 'c', (long)-4, (short)2, + (unsigned long)2); + } + break; + } + case MODE_FPRINTF: + { + FILE *f = fdopen(fdout, "w"); + + for (i = 0; i < niter; i++) { + fprintf(f, "Some message %s %s %c %li %d %lu\n", + str1, str2, 'c', (long)-4, (short)2, + (unsigned long)2); + fflush(f); + } + fclose(f); + break; + } + case MODE_SPRINTF: + { + static char buf[4096]; + + for (i = 0; i < niter; i++) { + sprintf(buf, "Some message %s %s %c %li %d %lu\n", + str1, str2, 'c', (long)-4, (short)2, + (unsigned long)2); + } + break; + } + default: + return 1; + } + + return 0; +usage: + fprintf(stderr, + "flog [--mode binary|dprintf] [--output stdout|stderr|filename] [--decode] [--iter number]\n" + "\n" + + "Examples:\n" + "\n" + + " - run 100000 iterations of instant message processing (immediate dprintf calls)\n" + "\n" + " flog -m dprintf -i 100000\n" + "\n" + + " - run 100000 iterations in binary mode without processing (queue messages only)\n" + "\n" + " flog -i 100000\n" + "\n" + + " - run 100000 iterations in binary mode with decoding after\n" + "\n" + " flog -i 100000 -d\n" + "\n" + + " - run 100000 iterations in binary mode with decoding after, writting results into 'out' file\n" + "\n" + " flog -i 100000 -d -o out\n" + "\n"); + return 1; +} diff --git a/flog/tests/test00 b/flog/tests/test00 new file mode 100755 index 0000000000..a7937e4a18 --- /dev/null +++ b/flog/tests/test00 @@ -0,0 +1,22 @@ +#!/bin/sh + +set -e -x + +echo Map a log file into memory +time ./flog run -i 1000000 -o /tmp/flog.raw.map +echo Write into a log file +time ./flog run -i 1000000 > /tmp/flog.raw +echo Use fprintf +time ./flog run -m fprintf -i 1000000 -o /tmp/flog.fprintf.txt +echo Use dprintf +time ./flog run -m dprintf -i 1000000 -o /tmp/flog.dprintf.txt +echo Use sprintf +time ./flog run -m sprintf -i 1000000 + +time ./flog run -d < /tmp/flog.raw > /tmp/flog.raw.txt +cmp /tmp/flog.raw.txt /tmp/flog.fprintf.txt + +time ./flog run -d < /tmp/flog.raw.map > /tmp/flog.raw.map.txt +cmp /tmp/flog.raw.map.txt /tmp/flog.fprintf.txt + +cmp /tmp/flog.dprintf.txt /tmp/flog.fprintf.txt From e18017285b69bf465f27a6ad46c17c70913e51d7 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 28 Sep 2020 07:04:00 +0000 Subject: [PATCH 007/204] flog: Missing varargs init or cleanup (VARARGS) CID 302713 (#1 of 1): Missing varargs init or cleanup (VARARGS) va_end was not called for argptr. Signed-off-by: Adrian Reber --- flog/src/flog.c | 1 + 1 file changed, 1 insertion(+) diff --git a/flog/src/flog.c b/flog/src/flog.c index 533625de61..40cce3fedc 100644 --- a/flog/src/flog.c +++ b/flog/src/flog.c @@ -186,6 +186,7 @@ int flog_encode_msg(int fdout, unsigned int nargs, unsigned int mask, const char p = memccpy(str_start, (void *)m->args[i], 0, mbuf_size - (str_start - mbuf)); if (p == NULL) { fprintf(stderr, "No memory for string argument\n"); + va_end(argptr); return -1; } m->args[i] = str_start - mbuf; From 265569a40f04326dc2b310eb5ddbac9c1cb989e3 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 6 Oct 2020 03:59:38 +0100 Subject: [PATCH 008/204] criu-ns: Use PID 1 on restore criu-ns performs double fork, which results in criu restore using PID=2. Thus, if a user is trying to restore a process with that PID, the restore will fail. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 56 +++++++++++++------------------------------------ 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index e065c59716..dc6da84012 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -67,12 +67,8 @@ def wrap_restore(): _errno = ctypes.get_errno() raise OSError(_errno, errno.errorcode[_errno]) - (r_pipe, w_pipe) = os.pipe() - - # Spawn the init - if os.fork() == 0: - os.close(r_pipe) - + criu_pid = os.fork() + if criu_pid == 0: # Mount new /proc if _mount(None, b"/", None, MS_SLAVE|MS_REC, None) != 0: _errno = ctypes.get_errno() @@ -83,44 +79,22 @@ def wrap_restore(): raise OSError(_errno, errno.errorcode[_errno]) # Spawn CRIU binary - criu_pid = os.fork() - if criu_pid == 0: - run_criu() - raise OSError(errno.ENOENT, "No such command") - - while True: - try: - (pid, status) = os.wait() - if pid == criu_pid: - status = os.WEXITSTATUS(status) - break - except OSError: - status = -251 - break - - os.write(w_pipe, b"%d" % status) - os.close(w_pipe) - - if status != 0: - sys.exit(status) - - while True: - try: - os.wait() - except OSError: - break - + run_criu() + raise OSError(errno.ENOENT, "No such command") sys.exit(0) # Wait for CRIU to exit and report the status back - os.close(w_pipe) - status = os.read(r_pipe, 1024) - if not status.isdigit(): - status_i = -252 - else: - status_i = int(status) - - return status_i + while True: + try: + (pid, status) = os.wait() + if pid == criu_pid: + status = os.WEXITSTATUS(status) + break + except OSError: + status = -251 + break + + return status def get_varg(args): From 53dd29e93a8cbaf4aea0e81de3de98a1bd2e1f8f Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 6 Oct 2020 21:25:23 +0100 Subject: [PATCH 009/204] cr-restore: Wait child & reap zombies if PID=1 When criu restore runs as PID=1 it has an additional responsibility to reap zombie processes. Signed-off-by: Radostin Stoyanov Signed-off-by: Andrei Vagin --- criu/cr-restore.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 589087f9fb..472d960dfc 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -2192,6 +2192,18 @@ static int write_restored_pid(void) return 0; } +static void reap_zombies(void) +{ + while (1) { + pid_t pid = wait(NULL); + if (pid == -1) { + if (errno != ECHILD) + pr_perror("Error while waiting for pids"); + return; + } + } +} + static int restore_root_task(struct pstree_item *init) { enum trace_flags flag = TRACE_ALL; @@ -2445,8 +2457,9 @@ static int restore_root_task(struct pstree_item *init) if (ret != 0) pr_err("Post-resume script ret code %d\n", ret); - if (!opts.restore_detach && !opts.exec_cmd) - wait(NULL); + if (!opts.restore_detach && !opts.exec_cmd) { + reap_zombies(); + } return 0; From 2ec05a0563a6700bd6f8372d95e1205e285d9a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20C=C5=82api=C5=84ski?= Date: Tue, 13 Oct 2020 01:47:09 +0200 Subject: [PATCH 010/204] compel: don't mmap parasite as RWX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some kernels have W^X mitigation, which means they won't execute memory blocks if that memory block is also writable or ever was writable. This patch enables CRIU to run on such kernels. 1. Align .data section to a page. 2. mmap a memory block for parasite as RX. 3. mprotect everything after .text as RW. Signed-off-by: Michał Cłapiński --- compel/arch/ppc64/scripts/compel-pack.lds.S | 2 +- compel/arch/s390/scripts/compel-pack.lds.S | 2 +- compel/arch/x86/scripts/compel-pack.lds.S | 2 +- compel/include/uapi/infect.h | 1 + compel/src/lib/handle-elf.c | 5 +++ compel/src/lib/infect.c | 48 +++++++++++++++++---- 6 files changed, 48 insertions(+), 12 deletions(-) diff --git a/compel/arch/ppc64/scripts/compel-pack.lds.S b/compel/arch/ppc64/scripts/compel-pack.lds.S index 572f1c42dd..f197fb9994 100644 --- a/compel/arch/ppc64/scripts/compel-pack.lds.S +++ b/compel/arch/ppc64/scripts/compel-pack.lds.S @@ -12,7 +12,7 @@ SECTIONS *(.compel.init) } - .data : { + .data : ALIGN(0x10000) { *(.data*) *(.bss*) } diff --git a/compel/arch/s390/scripts/compel-pack.lds.S b/compel/arch/s390/scripts/compel-pack.lds.S index 2571ac852c..a821189833 100644 --- a/compel/arch/s390/scripts/compel-pack.lds.S +++ b/compel/arch/s390/scripts/compel-pack.lds.S @@ -12,7 +12,7 @@ SECTIONS *(.compel.init) } - .data : { + .data : ALIGN(0x1000) { *(.data*) *(.bss*) } diff --git a/compel/arch/x86/scripts/compel-pack.lds.S b/compel/arch/x86/scripts/compel-pack.lds.S index 68ddb36226..44e705e299 100644 --- a/compel/arch/x86/scripts/compel-pack.lds.S +++ b/compel/arch/x86/scripts/compel-pack.lds.S @@ -13,7 +13,7 @@ SECTIONS *(.compel.init) } - .data : { + .data : ALIGN(0x1000) { *(.data*) *(.bss*) } diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h index 257658a70d..fa326eafec 100644 --- a/compel/include/uapi/infect.h +++ b/compel/include/uapi/infect.h @@ -155,6 +155,7 @@ struct parasite_blob_desc { unsigned long args_ptr_off; unsigned long got_off; unsigned long args_off; + unsigned long data_off; compel_reloc_t *relocs; unsigned int nr_relocs; } hdr; diff --git a/compel/src/lib/handle-elf.c b/compel/src/lib/handle-elf.c index 2319170ae0..e505f2c432 100644 --- a/compel/src/lib/handle-elf.c +++ b/compel/src/lib/handle-elf.c @@ -155,6 +155,7 @@ int __handle_elf(void *mem, size_t size) int64_t toc_offset = 0; #endif int ret = -EINVAL; + unsigned long data_off = 0; pr_debug("Header\n"); pr_debug("------------\n"); @@ -698,6 +699,9 @@ int __handle_elf(void *mem, size_t size) pr_out("\n\t"); pr_out("0x%02x,", shdata[j]); } + + if (!strcmp(&secstrings[sh->sh_name], ".data")) + data_off = sh->sh_addr; } pr_out("};\n"); pr_out("\n"); @@ -722,6 +726,7 @@ int __handle_elf(void *mem, size_t size) pr_out("\tpbd->hdr.args_ptr_off = %s_sym__export_parasite_service_args_ptr;\n", opts.prefix); pr_out("\tpbd->hdr.got_off = round_up(pbd->hdr.bsize, sizeof(long));\n"); pr_out("\tpbd->hdr.args_off = pbd->hdr.got_off + %zd*sizeof(long);\n", nr_gotpcrel); + pr_out("\tpbd->hdr.data_off = %#lx;\n", data_off); pr_out("\tpbd->hdr.relocs = %s_relocs;\n", opts.prefix); pr_out("\tpbd->hdr.nr_relocs = " "sizeof(%s_relocs) / sizeof(%s_relocs[0]);\n", diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 38846c21f1..5c4c1b18d0 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -690,12 +690,11 @@ static int parasite_start_daemon(struct parasite_ctl *ctl) return 0; } -static int parasite_mmap_exchange(struct parasite_ctl *ctl, unsigned long size) +static int parasite_mmap_exchange(struct parasite_ctl *ctl, unsigned long size, int remote_prot) { int fd; - ctl->remote_map = remote_mmap(ctl, NULL, size, - PROT_READ | PROT_WRITE | PROT_EXEC, + ctl->remote_map = remote_mmap(ctl, NULL, size, remote_prot, MAP_ANONYMOUS | MAP_SHARED, -1, 0); if (!ctl->remote_map) { pr_err("Can't allocate memory for parasite blob (pid: %d)\n", ctl->rpid); @@ -733,7 +732,7 @@ static void parasite_memfd_close(struct parasite_ctl *ctl, int fd) pr_err("Can't close memfd\n"); } -static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size) +static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size, int remote_prot) { void *where = (void *)ctl->ictx.syscall_ip + BUILTIN_SYSCALL_SIZE; bool compat_task = !compel_mode_native(ctl); @@ -785,8 +784,7 @@ static int parasite_memfd_exchange(struct parasite_ctl *ctl, unsigned long size) goto err_cure; } - ctl->remote_map = remote_mmap(ctl, NULL, size, - PROT_READ | PROT_WRITE | PROT_EXEC, + ctl->remote_map = remote_mmap(ctl, NULL, size, remote_prot, MAP_FILE | MAP_SHARED, fd, 0); if (!ctl->remote_map) { pr_err("Can't rmap memfd for parasite blob\n"); @@ -856,15 +854,47 @@ void compel_relocs_apply(void *mem, void *vbase, struct parasite_blob_desc *pbd) #endif } +long remote_mprotect(struct parasite_ctl *ctl, void *addr, size_t len, int prot) +{ + long ret; + int err; + bool compat_task = !user_regs_native(&ctl->orig.regs); + + err = compel_syscall(ctl, __NR(mprotect, compat_task), &ret, + (unsigned long)addr, len, prot, 0, 0, 0); + if (err < 0) { + pr_err("compel_syscall for mprotect failed\n"); + return -1; + } + return ret; +} + static int compel_map_exchange(struct parasite_ctl *ctl, unsigned long size) { - int ret; + int ret, remote_prot; - ret = parasite_memfd_exchange(ctl, size); + if (ctl->pblob.hdr.data_off) + remote_prot = PROT_READ | PROT_EXEC; + else + remote_prot = PROT_READ | PROT_WRITE | PROT_EXEC; + + ret = parasite_memfd_exchange(ctl, size, remote_prot); if (ret == 1) { pr_info("MemFD parasite doesn't work, goto legacy mmap\n"); - ret = parasite_mmap_exchange(ctl, size); + ret = parasite_mmap_exchange(ctl, size, remote_prot); + if (ret) + return ret; } + + if (!ctl->pblob.hdr.data_off) + return 0; + + ret = remote_mprotect(ctl, ctl->remote_map + ctl->pblob.hdr.data_off, + size - ctl->pblob.hdr.data_off, + PROT_READ | PROT_WRITE); + if (ret) + pr_err("remote_mprotect failed\n"); + return ret; } From b80dd7e7c0a526e67543cd926bdddbba2d359c95 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 06:17:32 +0000 Subject: [PATCH 011/204] lock: disable clang_analyzer for the LOCK_BUG_ON() macro The clang analyzer, scan-build, cannot correctly handle the LOCK_BUG_ON() macro. At multiple places there is the following warning: Error: CLANG_WARNING: criu/pie/restorer.c:1221:4: warning: Dereference of null pointer include/common/lock.h:14:35: note: expanded from macro 'LOCK_BUG_ON' *(volatile unsigned long *)NULL = 0xdead0000 + __LINE__ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~ This just disable the clang analyzer for the LOCK_BUG_ON() macro. Signed-off-by: Adrian Reber --- include/common/lock.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/common/lock.h b/include/common/lock.h index 4782b638f2..6baece25fa 100644 --- a/include/common/lock.h +++ b/include/common/lock.h @@ -9,10 +9,13 @@ #include "common/asm/atomic.h" #include "common/compiler.h" +/* scan-build complains about derefencing a NULL pointer here. */ +#ifndef __clang_analyzer__ #define LOCK_BUG_ON(condition) \ if ((condition)) \ *(volatile unsigned long *)NULL = 0xdead0000 + __LINE__ #define LOCK_BUG() LOCK_BUG_ON(1) +#endif /* __clang_analyzer__ */ #ifdef CR_NOGLIBC # include From e13a7ecd276909344210734f3d5017ae30d9e056 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 07:21:19 +0000 Subject: [PATCH 012/204] infect: initialize struct to avoid CLANG_WARNING Using scan-build there is a warning about infect.c:231:17: warning: The left operand of '!=' is a garbage value if (ss->state != 'Z') { which is a false positive as every process will have a 'Status' field, but initializing the structure makes the clang analyzer silent. Signed-off-by: Adrian Reber --- compel/src/lib/infect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 5c4c1b18d0..4f2402feeb 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -105,7 +105,7 @@ static int parse_pid_status(int pid, struct seize_task_status *ss, void *data) int compel_stop_task(int pid) { int ret; - struct seize_task_status ss; + struct seize_task_status ss = {}; ret = compel_interrupt_task(pid); if (ret == 0) From 6a9bff88b5834d9997df09d1b07de9906bec20f4 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 29 Sep 2020 11:16:54 +0000 Subject: [PATCH 013/204] lib/py: remove unused variable Signed-off-by: Adrian Reber --- lib/py/images/images.py | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/py/images/images.py b/lib/py/images/images.py index 9c8e1447de..b4b55c9107 100644 --- a/lib/py/images/images.py +++ b/lib/py/images/images.py @@ -418,7 +418,6 @@ def load(self, f, pbuff): return messages def dump(self, extra, f, pbuff): - entry = pb2dict.pb2dict(pbuff) for i in range(0, len(extra), 2): msg = pb.ipc_msg() pb2dict.dict2pb(extra[i], msg) From bbca79ab66a5e3b9c26879125eb1e0d83feed2b0 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 29 Sep 2020 11:18:09 +0000 Subject: [PATCH 014/204] coredump: remove two unused variables Signed-off-by: Adrian Reber --- coredump/criu_coredump/coredump.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/coredump/criu_coredump/coredump.py b/coredump/criu_coredump/coredump.py index 68dc16bf2f..459714da61 100644 --- a/coredump/criu_coredump/coredump.py +++ b/coredump/criu_coredump/coredump.py @@ -523,7 +523,6 @@ class mmaped_file_info: continue shmid = vma["shmid"] - size = vma["end"] - vma["start"] off = vma["pgoff"] / PAGESIZE files = self.reg_files @@ -822,8 +821,6 @@ class vma_class: for vma in mm["vmas"]: size = self._get_vma_dump_size(vma) - chunk = self._gen_mem_chunk(pid, vma, size) - v = vma_class() v.filesz = self._get_vma_dump_size(vma) v.data = self._gen_mem_chunk(pid, vma, v.filesz) From 407d3fe0fea253d4336787e512a64bb6545f741a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 29 Sep 2020 11:18:37 +0000 Subject: [PATCH 015/204] bfd: remove unused line Signed-off-by: Adrian Reber --- criu/bfd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/criu/bfd.c b/criu/bfd.c index 05824551b6..535c4d3549 100644 --- a/criu/bfd.c +++ b/criu/bfd.c @@ -198,8 +198,7 @@ char *breadchr(struct bfd *f, char c) if (b->sz == BUFSIZE) { pr_err("The bfd buffer is too small\n"); - ERR_PTR(-EIO); - return NULL; + return ERR_PTR(-EIO); } /* * Last bytes may lack the \n at the From eb741528f19e5e101eb8904760d13bf12a489d91 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 29 Sep 2020 11:22:26 +0000 Subject: [PATCH 016/204] Use 'is None' instead of '== None' Signed-off-by: Adrian Reber --- coredump/criu_coredump/coredump.py | 2 +- lib/py/cli.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/coredump/criu_coredump/coredump.py b/coredump/criu_coredump/coredump.py index 459714da61..b37ef22913 100644 --- a/coredump/criu_coredump/coredump.py +++ b/coredump/criu_coredump/coredump.py @@ -718,7 +718,7 @@ def _gen_mem_chunk(self, pid, vma, size): # than one from maped file on disk. page = page_mem - if page == None: + if page is None: # Hole page = PAGESIZE * "\0" diff --git a/lib/py/cli.py b/lib/py/cli.py index da343022e6..94cc2f9475 100755 --- a/lib/py/cli.py +++ b/lib/py/cli.py @@ -133,7 +133,7 @@ def ftype_find_in_image(opts, ft, fid, img): if f: return f[ft['field']] - if ft['img'] == None: + if ft['img'] is None: ft['img'] = pycriu.images.load(dinf(opts, img))['entries'] for f in ft['img']: if f['id'] == fid: From 84ffb965c29b56abfde0ba87921860f614ec053a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 29 Sep 2020 11:28:35 +0000 Subject: [PATCH 017/204] sk-unix: do not overwrite function parameter The function collect_one_unixsk() has a parameter 'i' and at the same time has a variable, in a loop, with the name 'i'. This is no real error or problem, because the function parameter 'i' is never used in the whole function. Just trying to reduce confusion and making a code checker happy. Signed-off-by: Adrian Reber --- criu/sk-unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/criu/sk-unix.c b/criu/sk-unix.c index 00d09cc114..5fcc0b4615 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -2118,10 +2118,10 @@ static int collect_one_unixsk(void *o, ProtobufCMessage *base, struct cr_img *i) if (memrchr(uname, 0, ulen)) { /* replace zero characters */ char *s = alloca(ulen + 1); - int i; + int j; - for (i = 0; i < ulen; i++) - s[i] = uname[i] ? : '@'; + for (j = 0; j < ulen; j++) + s[j] = uname[j] ? : '@'; uname = s; } } else if (ulen == 0) { From 42e3e2e8439dbf900c60086acb8cde823315fe26 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 10:37:41 +0000 Subject: [PATCH 018/204] autofs: Potential leak of memory pointed to by 'token' Using strsep() moves the pointer of the original string and this introduces a copy of the malloc()ed memory to be able to free() it later. Signed-off-by: Adrian Reber --- criu/autofs.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/criu/autofs.c b/criu/autofs.c index 3e93b7b851..c35ef39db8 100644 --- a/criu/autofs.c +++ b/criu/autofs.c @@ -330,11 +330,11 @@ static int parse_options(char *options, AutofsEntry *entry, long *pipe_ino) static int autofs_revisit_options(struct mount_info *pm) { FILE *f; - char *str; + char *buf; int ret = -ENOMEM; - str = xmalloc(1024); - if (!str) { + buf = xmalloc(1024); + if (!buf) { return -ENOMEM; } @@ -342,8 +342,9 @@ static int autofs_revisit_options(struct mount_info *pm) if (!f) goto free_str; - while (fgets(str, 1024, f)) { + while (fgets(buf, 1024, f)) { int mnt_id = -1; + char *str = buf; char *token; /* Removing '/n' */ @@ -376,7 +377,7 @@ static int autofs_revisit_options(struct mount_info *pm) close_proc: fclose(f); free_str: - free(str); + free(buf); return ret; } From 62ab67ed5a3193af79a6f0422dd857fe1ef5e965 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 10:42:46 +0000 Subject: [PATCH 019/204] coverity: ignore CHECKED_RETURN Ignore coverity errors about CHECKED_RETURN. Signed-off-by: Adrian Reber --- criu/autofs.c | 1 + criu/cgroup.c | 1 + criu/mount.c | 3 +++ criu/net.c | 1 + 4 files changed, 6 insertions(+) diff --git a/criu/autofs.c b/criu/autofs.c index c35ef39db8..8b25308d97 100644 --- a/criu/autofs.c +++ b/criu/autofs.c @@ -433,6 +433,7 @@ static int access_autofs_mount(struct mount_info *pm) case 0: /* We don't care about results. * All we need is to "touch" */ + /* coverity[check_return] */ openat(autofs_mnt, mnt_path, O_RDONLY|O_NONBLOCK|O_DIRECTORY); _exit(0); diff --git a/criu/cgroup.c b/criu/cgroup.c index e7e15bc512..8576ee2f13 100644 --- a/criu/cgroup.c +++ b/criu/cgroup.c @@ -1940,6 +1940,7 @@ static int rewrite_cgroup_roots(CgroupEntry *cge) list_for_each_entry(o, &opts.new_cgroup_roots, node) { unsigned old_mask = ctrl_mask; + /* coverity[check_return] */ cgroup_contains(ctrl->cnames, ctrl->n_cnames, o->controller, &ctrl_mask); if (old_mask != ctrl_mask) { diff --git a/criu/mount.c b/criu/mount.c index 25ef7f09eb..2d6ee66dba 100644 --- a/criu/mount.c +++ b/criu/mount.c @@ -1188,6 +1188,7 @@ bool mnt_is_overmounted(struct mount_info *mi) static int set_is_overmounted(struct mount_info *mi) { + /* coverity[check_return] */ mnt_is_overmounted(mi); return 0; } @@ -1444,6 +1445,7 @@ int open_mountpoint(struct mount_info *pm) return __open_mountpoint(pm, fd); err: if (ns_old >= 0) + /* coverity[check_return] */ restore_ns(ns_old, &mnt_ns_desc); close_safe(&fd); if (fchdir(cwd_fd)) @@ -3508,6 +3510,7 @@ int prepare_mnt_ns(void) return ret; err: if (rst >= 0) + /* coverity[check_return] */ restore_ns(rst, &mnt_ns_desc); return -1; } diff --git a/criu/net.c b/criu/net.c index 4f1f7d47f4..91990412f9 100644 --- a/criu/net.c +++ b/criu/net.c @@ -2930,6 +2930,7 @@ void network_unlock(void) rst_unlock_tcp_connections(); if (root_ns_mask & CLONE_NEWNET) { + /* coverity[check_return] */ run_scripts(ACT_NET_UNLOCK); network_unlock_internal(); } From 36f9700b13002cdfa0243a279e10b2fd9bfac32a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 13:38:48 +0000 Subject: [PATCH 020/204] vdso-compat: let coverity know that the function does not return Signed-off-by: Adrian Reber --- criu/vdso-compat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/criu/vdso-compat.c b/criu/vdso-compat.c index a68c0bacea..8f5d19e102 100644 --- a/criu/vdso-compat.c +++ b/criu/vdso-compat.c @@ -13,6 +13,7 @@ static void exit_on(int ret, int err_fd, char *reason) if (ret) { syscall(__NR_write, err_fd, reason, strlen(reason)); syscall(__NR_exit, ret); + __builtin_unreachable(); } } /* From 53501e5e83a11b8fae5eacb844bdab02d4a1b247 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 14:57:55 +0000 Subject: [PATCH 021/204] cr-dump: Potential leak of memory pointed to by 'si' Signed-off-by: Adrian Reber --- criu/cr-dump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/criu/cr-dump.c b/criu/cr-dump.c index b9d29145cc..4a839b3f6d 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -946,6 +946,7 @@ static int dump_signal_queue(pid_t tid, SignalQueueEntry **sqe, bool group) } else pr_perror("ptrace"); + xfree(si); break; } From 73ed071e058d83c7ae7f0de5d01980be9f41899b Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 15:06:55 +0000 Subject: [PATCH 022/204] restore: Value stored to 'ret' is never read Signed-off-by: Adrian Reber --- criu/cr-restore.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 472d960dfc..d94db5fd3e 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1404,8 +1404,6 @@ static inline int fork_with_pid(struct pstree_item *item) ca.core = NULL; } - ret = -1; - ca.item = item; ca.clone_flags = rsti(item)->clone_flags; From fc20d280c3ef2c4a37b0080760a87f0c174a360d Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 16:49:35 +0000 Subject: [PATCH 023/204] coverity: fix parameter_hidden: declaration hides parameter Signed-off-by: Adrian Reber --- criu/libnetlink.c | 6 +++--- criu/path.c | 6 +++--- criu/pstree.c | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/criu/libnetlink.c b/criu/libnetlink.c index 18a323b8d3..f9da58e9a4 100644 --- a/criu/libnetlink.c +++ b/criu/libnetlink.c @@ -20,9 +20,9 @@ static int nlmsg_receive(char *buf, int len, if (hdr->nlmsg_seq != CR_NLMSG_SEQ) continue; if (hdr->nlmsg_type == NLMSG_DONE) { - int *len = (int *)NLMSG_DATA(hdr); - if (*len < 0) - return err_cb(*len, ns, arg); + int *length = (int *)NLMSG_DATA(hdr); + if (*length < 0) + return err_cb(*length, ns, arg); return 0; } if (hdr->nlmsg_type == NLMSG_ERROR) { diff --git a/criu/path.c b/criu/path.c index 22a89a4aa6..637d0fae2f 100644 --- a/criu/path.c +++ b/criu/path.c @@ -88,11 +88,11 @@ char *mnt_get_sibling_path(struct mount_info *m, len -= off; path += off; } else { - int len = strlen(cut_root); - if (strncmp(rpath, cut_root, len)) + int length = strlen(cut_root); + if (strncmp(rpath, cut_root, length)) return NULL; rpath += strlen(cut_root); - if (len > 0 && (rpath[0] && rpath[0] != '/')) + if (length > 0 && (rpath[0] && rpath[0] != '/')) return NULL; } if (rpath[0] == '/') diff --git a/criu/pstree.c b/criu/pstree.c index a876615fb0..f1513dc81a 100644 --- a/criu/pstree.c +++ b/criu/pstree.c @@ -674,12 +674,12 @@ static int prepare_pstree_ids(pid_t pid) leader = pstree_item_by_virt(item->sid); BUG_ON(leader == NULL); if (leader->pid->state != TASK_UNDEF) { - pid_t pid; + pid_t helper_pid; - pid = get_free_pid(); - if (pid < 0) + helper_pid = get_free_pid(); + if (helper_pid < 0) break; - helper = lookup_create_item(pid); + helper = lookup_create_item(helper_pid); if (helper == NULL) return -1; @@ -771,15 +771,15 @@ static int prepare_pstree_ids(pid_t pid) /* Add a process group leader if it is absent */ for_each_pstree_item(item) { - struct pid *pid; + struct pid *pgid; if (!item->pgid || vpid(item) == item->pgid) continue; - pid = pstree_pid_by_virt(item->pgid); - if (pid->state != TASK_UNDEF) { - BUG_ON(pid->state == TASK_THREAD); - rsti(item)->pgrp_leader = pid->item; + pgid = pstree_pid_by_virt(item->pgid); + if (pgid->state != TASK_UNDEF) { + BUG_ON(pgid->state == TASK_THREAD); + rsti(item)->pgrp_leader = pgid->item; continue; } @@ -791,7 +791,7 @@ static int prepare_pstree_ids(pid_t pid) if (current_pgid == item->pgid) continue; - helper = pid->item; + helper = pgid->item; helper->sid = item->sid; helper->pgid = item->pgid; From 5527329ba209b2855fbc588943873e6b1dc14bfa Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 17:05:15 +0000 Subject: [PATCH 024/204] dump: Potential leak of memory pointed to by 'si' Signed-off-by: Adrian Reber --- criu/cr-dump.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 4a839b3f6d..10b13f17d1 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -936,8 +936,10 @@ static int dump_signal_queue(pid_t tid, SignalQueueEntry **sqe, bool group) } nr = ret = ptrace(PTRACE_PEEKSIGINFO, tid, &arg, si); - if (ret == 0) + if (ret == 0) { + xfree(si); break; /* Finished */ + } if (ret < 0) { if (errno == EIO) { @@ -954,6 +956,7 @@ static int dump_signal_queue(pid_t tid, SignalQueueEntry **sqe, bool group) queue->signals = xrealloc(queue->signals, sizeof(*queue->signals) * queue->n_signals); if (!queue->signals) { ret = -1; + xfree(si); break; } From d95c2683b9f6e059ac53bbab79a3326f602b1e99 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Oct 2020 06:27:17 +0000 Subject: [PATCH 025/204] util: fix double_close false positive Coverity does not understand how close_fds() works. Signed-off-by: Adrian Reber --- criu/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/criu/util.c b/criu/util.c index 27751880c8..670ef158d6 100644 --- a/criu/util.c +++ b/criu/util.c @@ -534,6 +534,7 @@ static int close_fds(int minfd) continue; if (fd < minfd) continue; + /* coverity[double_close] */ close(fd); } closedir(dir); From ef4ec3261c5f9f535a8e6fb59c85f86754fe0d96 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 15:03:10 +0000 Subject: [PATCH 026/204] cr-dump: get_service_fd() is passed to a parameter that cannot be negative Signed-off-by: Adrian Reber --- criu/cr-dump.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 10b13f17d1..193a49c4d8 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1099,8 +1099,16 @@ static int dump_zombies(void) int ret = -1; int pidns = root_ns_mask & CLONE_NEWPID; - if (pidns && set_proc_fd(get_service_fd(CR_PROC_FD_OFF))) - return -1; + if (pidns) { + int fd; + + fd = get_service_fd(CR_PROC_FD_OFF); + if (fd < 0) + return -1; + + if (set_proc_fd(fd)) + return -1; + } /* * We dump zombies separately because for pid-ns case From 84df563c5c9781517a19f0e8df1d1f6ed53f007d Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Oct 2020 08:23:01 +0000 Subject: [PATCH 027/204] sk-unix: ignore coverity chroot() warning criu/sk-unix.c:1173: chroot_call: Calling chroot: "chroot(".")". criu/sk-unix.c:1175: chroot: Calling function "close_safe" after chroot() but before calling chdir("/"). criu/sk-unix.c:1251: chroot_call: Calling chroot: "chroot(".")". criu/sk-unix.c:1263: chroot: Calling function "print_on_level" after chroot() but before calling chdir("/"). Coverity also says: 175312, 175313 Insecure chroot If a call to chroot is not followed by a call to chdir("/") the chroot jail confinement can be violated. Signed-off-by: Adrian Reber --- criu/sk-unix.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/criu/sk-unix.c b/criu/sk-unix.c index 5fcc0b4615..a3964081b8 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -1170,6 +1170,7 @@ static int revert_unix_sk_cwd(struct unix_sk_info *ui, int *prev_cwd_fd, int *ro if (*ns_fd >= 0 && restore_ns(*ns_fd, &mnt_ns_desc)) ret = -1; if (*root_fd >= 0) { + /* coverity[chroot_call] */ if (fchdir(*root_fd) || chroot(".")) pr_perror("Can't revert root directory"); close_safe(root_fd); @@ -1248,6 +1249,7 @@ static int prep_unix_sk_cwd(struct unix_sk_info *ui, int *prev_cwd_fd, goto err; } close(fd); + /* coverity[chroot_call] */ if (chroot(".")) { pr_perror("Unable to change root directory"); goto err; From cec432500d375f05eff908bd5216fe705420155c Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Oct 2020 08:46:26 +0000 Subject: [PATCH 028/204] coverity: img_raw_fd() returns a negative number criu/pagemap.c:245: negative_return_fn: Function "img_raw_fd(pr->pi)" returns a negative number. criu/pagemap.c:245: assign: Assigning: "fd" = "img_raw_fd(pr->pi)". criu/pagemap.c:258: negative_returns: "fd" is passed to a parameter that cannot be negative. criu/ipc_ns.c:762: negative_return_fn: Function "img_raw_fd(img)" returns a negative number. criu/ipc_ns.c:762: assign: Assigning: "ifd" = "img_raw_fd(img)". criu/ipc_ns.c:768: negative_returns: "ifd" is passed to a parameter that cannot be negative. Signed-off-by: Adrian Reber --- criu/ipc_ns.c | 4 ++++ criu/pagemap.c | 7 ++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/criu/ipc_ns.c b/criu/ipc_ns.c index 915aea20b2..e7049599f9 100644 --- a/criu/ipc_ns.c +++ b/criu/ipc_ns.c @@ -760,6 +760,10 @@ static int restore_content(void *data, struct cr_img *img, const IpcShmEntry *sh ssize_t size, off; ifd = img_raw_fd(img); + if (ifd < 0) { + pr_err("Failed getting raw image fd\n"); + return -1; + } size = round_up(shm->size, sizeof(u32)); off = 0; do { diff --git a/criu/pagemap.c b/criu/pagemap.c index 33bce10e37..abcdcdfd5e 100644 --- a/criu/pagemap.c +++ b/criu/pagemap.c @@ -242,10 +242,15 @@ static int read_parent_page(struct page_read *pr, unsigned long vaddr, static int read_local_page(struct page_read *pr, unsigned long vaddr, unsigned long len, void *buf) { - int fd = img_raw_fd(pr->pi); + int fd; ssize_t ret; size_t curr = 0; + fd = img_raw_fd(pr->pi); + if (fd < 0) { + pr_err("Failed getting raw image fd\n"); + return -1; + } /* * Flush any pending async requests if any not to break the * linear reading from the pages.img file. From 2d290eeb0a5aee233f8c1cf330336a6c2e54f562 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Oct 2020 10:15:04 +0000 Subject: [PATCH 029/204] namespaces: fix 'Declaring variable "path" without initializer' criu/namespaces.c:529: var_decl: Declaring variable "path" without initializer. criu/namespaces.c:602: uninit_use_in_call: Using uninitialized value "*path" as argument to "%s" when calling "print_on_level". Signed-off-by: Adrian Reber --- criu/namespaces.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/criu/namespaces.c b/criu/namespaces.c index 796f412c56..384c9ca0c0 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -537,7 +537,10 @@ static int open_ns_fd(struct file_desc *d, int *new_fd) else break; fd = fdstore_get(nsfd_id); - goto check_open; + if (fd < 0) { + return -1; + } + goto out; } /* @@ -597,12 +600,11 @@ static int open_ns_fd(struct file_desc *d, int *new_fd) path[sizeof(path) - 1] = '\0'; fd = open(path, nfi->nfe->flags); -check_open: if (fd < 0) { pr_perror("Can't open file %s on restore", path); return fd; } - +out: *new_fd = fd; return 0; } From 0e47308d0f64d54c70b4a39d18e41db82bbd7733 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 3 Nov 2020 10:18:02 +0000 Subject: [PATCH 030/204] CI: rename 'travis' to 'ci' CRIU is already using multiple CI systems and not just Travis. This renames all Travis related things to 'ci' to show it is actually independent of Travis. Just a simple rename. Signed-off-by: Adrian Reber --- .../workflows/cross-compile-daily-mips.yml | 2 +- .github/workflows/cross-compile-daily.yml | 2 +- .github/workflows/cross-compile-mips.yml | 2 +- .github/workflows/cross-compile.yml | 2 +- .travis.yml | 4 +-- Makefile | 2 +- scripts/build/Dockerfile.aarch64-cross | 2 +- scripts/build/Dockerfile.armv7-cross | 2 +- scripts/build/Dockerfile.linux32.tmpl | 2 +- scripts/build/Dockerfile.mips64el-cross | 2 +- scripts/build/Dockerfile.openj9-ubuntu | 2 +- scripts/build/Dockerfile.ppc64-cross | 2 +- scripts/build/Dockerfile.tmpl | 2 +- scripts/build/Dockerfile.x86_64.hdr | 2 +- scripts/{travis => ci}/Makefile | 8 ++--- scripts/{travis => ci}/apt-install | 0 scripts/{travis => ci}/asan.sh | 0 .../ci-after-success.sh} | 0 scripts/{travis => ci}/docker-test.sh | 4 +-- scripts/{travis => ci}/docker.env | 2 +- scripts/{travis => ci}/openj9-test.sh | 0 scripts/{travis => ci}/podman-test.sh | 4 +-- .../travis-tests => ci/run-ci-tests.sh} | 30 +++++++++---------- scripts/{travis => ci}/vagrant.sh | 0 24 files changed, 39 insertions(+), 39 deletions(-) rename scripts/{travis => ci}/Makefile (92%) rename scripts/{travis => ci}/apt-install (100%) rename scripts/{travis => ci}/asan.sh (100%) rename scripts/{travis/travis-after_success => ci/ci-after-success.sh} (100%) rename scripts/{travis => ci}/docker-test.sh (97%) rename scripts/{travis => ci}/docker.env (83%) rename scripts/{travis => ci}/openj9-test.sh (100%) rename scripts/{travis => ci}/podman-test.sh (98%) rename scripts/{travis/travis-tests => ci/run-ci-tests.sh} (91%) rename scripts/{travis => ci}/vagrant.sh (100%) diff --git a/.github/workflows/cross-compile-daily-mips.yml b/.github/workflows/cross-compile-daily-mips.yml index b372a23ae3..164f09c99b 100644 --- a/.github/workflows/cross-compile-daily-mips.yml +++ b/.github/workflows/cross-compile-daily-mips.yml @@ -19,4 +19,4 @@ jobs: ref: ${{ matrix.branches }} - name: Run Cross Compilation Targets run: > - sudo make -C scripts/travis ${{ matrix.target }} + sudo make -C scripts/ci ${{ matrix.target }} diff --git a/.github/workflows/cross-compile-daily.yml b/.github/workflows/cross-compile-daily.yml index 78e9c1619c..aed08f2c98 100644 --- a/.github/workflows/cross-compile-daily.yml +++ b/.github/workflows/cross-compile-daily.yml @@ -19,4 +19,4 @@ jobs: ref: ${{ matrix.branches }} - name: Run Cross Compilation Targets run: > - sudo make -C scripts/travis ${{ matrix.target }} + sudo make -C scripts/ci ${{ matrix.target }} diff --git a/.github/workflows/cross-compile-mips.yml b/.github/workflows/cross-compile-mips.yml index 4f6c6dbd39..3b475ff030 100644 --- a/.github/workflows/cross-compile-mips.yml +++ b/.github/workflows/cross-compile-mips.yml @@ -18,4 +18,4 @@ jobs: - uses: actions/checkout@v2 - name: Run Cross Compilation Targets run: > - sudo make -C scripts/travis ${{ matrix.target }} + sudo make -C scripts/ci ${{ matrix.target }} diff --git a/.github/workflows/cross-compile.yml b/.github/workflows/cross-compile.yml index 3b007cdd09..d8143b397e 100644 --- a/.github/workflows/cross-compile.yml +++ b/.github/workflows/cross-compile.yml @@ -14,4 +14,4 @@ jobs: - uses: actions/checkout@v2 - name: Run Cross Compilation Targets run: > - sudo make -C scripts/travis ${{ matrix.target }} + sudo make -C scripts/ci ${{ matrix.target }} diff --git a/.travis.yml b/.travis.yml index 08d0b2ed6d..d6ee9a3990 100644 --- a/.travis.yml +++ b/.travis.yml @@ -94,7 +94,7 @@ jobs: - env: TR_ARCH=fedora-rawhide - env: TR_ARCH=local GCOV=1 script: - - sudo make CCACHE=1 -C scripts/travis $TR_ARCH + - sudo make CCACHE=1 -C scripts/ci $TR_ARCH after_success: - ccache -s - - make -C scripts/travis after_success + - make -C scripts/ci after_success diff --git a/Makefile b/Makefile index d1f910960d..ed1544315a 100644 --- a/Makefile +++ b/Makefile @@ -411,7 +411,7 @@ lint: flake8 --config=scripts/flake8.cfg test/others/rpc/config_file.py flake8 --config=scripts/flake8.cfg lib/py/images/pb2dict.py shellcheck scripts/*.sh - shellcheck scripts/travis/*.sh scripts/travis/travis* scripts/travis/apt-install + shellcheck scripts/ci/*.sh scripts/ci/apt-install include Makefile.install diff --git a/scripts/build/Dockerfile.aarch64-cross b/scripts/build/Dockerfile.aarch64-cross index ab5d9299fc..d372b2c91f 100644 --- a/scripts/build/Dockerfile.aarch64-cross +++ b/scripts/build/Dockerfile.aarch64-cross @@ -1,6 +1,6 @@ FROM dockcross/base:latest -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install # Add the cross compiler sources RUN echo "deb http://ftp.us.debian.org/debian/ buster main" >> /etc/apt/sources.list && \ diff --git a/scripts/build/Dockerfile.armv7-cross b/scripts/build/Dockerfile.armv7-cross index 99321e456c..b3a18d0ec7 100644 --- a/scripts/build/Dockerfile.armv7-cross +++ b/scripts/build/Dockerfile.armv7-cross @@ -1,6 +1,6 @@ FROM dockcross/base:latest -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install # Add the cross compiler sources RUN echo "deb http://ftp.us.debian.org/debian/ buster main" >> /etc/apt/sources.list && \ diff --git a/scripts/build/Dockerfile.linux32.tmpl b/scripts/build/Dockerfile.linux32.tmpl index 3b3007e9c2..49eaeb3b23 100644 --- a/scripts/build/Dockerfile.linux32.tmpl +++ b/scripts/build/Dockerfile.linux32.tmpl @@ -1,7 +1,7 @@ ARG CC=gcc ARG ENV1=FOOBAR -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install RUN apt-install \ ccache \ diff --git a/scripts/build/Dockerfile.mips64el-cross b/scripts/build/Dockerfile.mips64el-cross index 0458ee887e..6f0f32820f 100644 --- a/scripts/build/Dockerfile.mips64el-cross +++ b/scripts/build/Dockerfile.mips64el-cross @@ -1,6 +1,6 @@ FROM dockcross/base:latest -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install # Add the cross compiler sources RUN echo "deb http://ftp.us.debian.org/debian/ buster main" >> /etc/apt/sources.list && \ diff --git a/scripts/build/Dockerfile.openj9-ubuntu b/scripts/build/Dockerfile.openj9-ubuntu index 80af38b1a2..0663eb7ccf 100644 --- a/scripts/build/Dockerfile.openj9-ubuntu +++ b/scripts/build/Dockerfile.openj9-ubuntu @@ -1,6 +1,6 @@ FROM adoptopenjdk/openjdk8-openj9:latest -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install RUN apt-install protobuf-c-compiler \ libprotobuf-c-dev \ diff --git a/scripts/build/Dockerfile.ppc64-cross b/scripts/build/Dockerfile.ppc64-cross index fb93a5824e..eaa4e4ea22 100644 --- a/scripts/build/Dockerfile.ppc64-cross +++ b/scripts/build/Dockerfile.ppc64-cross @@ -1,6 +1,6 @@ FROM dockcross/base:latest -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install # Add the cross compiler sources RUN echo "deb http://ftp.us.debian.org/debian/ buster main" >> /etc/apt/sources.list && \ diff --git a/scripts/build/Dockerfile.tmpl b/scripts/build/Dockerfile.tmpl index f4213cea04..2e02d902cc 100644 --- a/scripts/build/Dockerfile.tmpl +++ b/scripts/build/Dockerfile.tmpl @@ -1,7 +1,7 @@ ARG CC=gcc ARG ENV1=FOOBAR -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install RUN apt-install \ ccache \ diff --git a/scripts/build/Dockerfile.x86_64.hdr b/scripts/build/Dockerfile.x86_64.hdr index 2f87c4e8cf..7e93c8cc43 100644 --- a/scripts/build/Dockerfile.x86_64.hdr +++ b/scripts/build/Dockerfile.x86_64.hdr @@ -1,5 +1,5 @@ FROM ubuntu:xenial -COPY scripts/travis/apt-install /bin/apt-install +COPY scripts/ci/apt-install /bin/apt-install RUN apt-install gcc-multilib diff --git a/scripts/travis/Makefile b/scripts/ci/Makefile similarity index 92% rename from scripts/travis/Makefile rename to scripts/ci/Makefile index 1af60fe8dc..513d58bfb3 100644 --- a/scripts/travis/Makefile +++ b/scripts/ci/Makefile @@ -1,9 +1,9 @@ local: - ./travis-tests + ./run-ci-tests.sh .PHONY: local after_success: - ./travis-after_success + ./ci-after-success.sh .PHONY: after_success target-suffix = @@ -46,11 +46,11 @@ restart-docker: $(TARGETS): restart-docker $(MAKE) -C ../build $@$(target-suffix) - docker run --env-file docker.env $(CONTAINER_OPTS) criu-$@ scripts/travis/travis-tests + docker run --env-file docker.env $(CONTAINER_OPTS) criu-$@ scripts/ci/run-ci-tests.sh fedora-asan: restart-docker $(MAKE) -C ../build $@$(target-suffix) - docker run -it $(CONTAINER_OPTS) criu-$@ ./scripts/travis/asan.sh $(ZDTM_OPTIONS) + docker run -it $(CONTAINER_OPTS) criu-$@ ./scripts/ci/asan.sh $(ZDTM_OPTIONS) docker-test: ./docker-test.sh diff --git a/scripts/travis/apt-install b/scripts/ci/apt-install similarity index 100% rename from scripts/travis/apt-install rename to scripts/ci/apt-install diff --git a/scripts/travis/asan.sh b/scripts/ci/asan.sh similarity index 100% rename from scripts/travis/asan.sh rename to scripts/ci/asan.sh diff --git a/scripts/travis/travis-after_success b/scripts/ci/ci-after-success.sh similarity index 100% rename from scripts/travis/travis-after_success rename to scripts/ci/ci-after-success.sh diff --git a/scripts/travis/docker-test.sh b/scripts/ci/docker-test.sh similarity index 97% rename from scripts/travis/docker-test.sh rename to scripts/ci/docker-test.sh index a6990b1801..e42e965694 100755 --- a/scripts/travis/docker-test.sh +++ b/scripts/ci/docker-test.sh @@ -32,9 +32,9 @@ fi service docker restart -export SKIP_TRAVIS_TEST=1 +export SKIP_CI_TEST=1 -./travis-tests +./run-ci-tests.sh cd ../../ diff --git a/scripts/travis/docker.env b/scripts/ci/docker.env similarity index 83% rename from scripts/travis/docker.env rename to scripts/ci/docker.env index 36154df0d6..399ced6941 100644 --- a/scripts/travis/docker.env +++ b/scripts/ci/docker.env @@ -1,4 +1,4 @@ -SKIP_TRAVIS_PREP=1 +SKIP_CI_PREP=1 ZDTM_OPTS=-x zdtm/static/binfmt_misc -x zdtm/static/sched_policy00 CC=gcc SKIP_EXT_DEV_TEST=1 diff --git a/scripts/travis/openj9-test.sh b/scripts/ci/openj9-test.sh similarity index 100% rename from scripts/travis/openj9-test.sh rename to scripts/ci/openj9-test.sh diff --git a/scripts/travis/podman-test.sh b/scripts/ci/podman-test.sh similarity index 98% rename from scripts/travis/podman-test.sh rename to scripts/ci/podman-test.sh index 509113994f..f56d10a74f 100755 --- a/scripts/travis/podman-test.sh +++ b/scripts/ci/podman-test.sh @@ -17,9 +17,9 @@ apt-get -y purge docker-ce ./apt-install podman containernetworking-plugins -export SKIP_TRAVIS_TEST=1 +export SKIP_CI_TEST=1 -./travis-tests +./run-ci-tests.sh cd ../../ diff --git a/scripts/travis/travis-tests b/scripts/ci/run-ci-tests.sh similarity index 91% rename from scripts/travis/travis-tests rename to scripts/ci/run-ci-tests.sh index 9e11054494..fab392ff24 100755 --- a/scripts/travis/travis-tests +++ b/scripts/ci/run-ci-tests.sh @@ -1,7 +1,7 @@ #!/bin/bash set -x -e -TRAVIS_PKGS="protobuf-c-compiler libprotobuf-c-dev libaio-dev libgnutls28-dev +CI_PKGS="protobuf-c-compiler libprotobuf-c-dev libaio-dev libgnutls28-dev libgnutls30 libprotobuf-dev protobuf-compiler libcap-dev libnl-3-dev gdb bash libnet-dev util-linux asciidoctor libnl-route-3-dev time ccache flake8 libbsd-dev" @@ -15,11 +15,11 @@ if [ -e /etc/lsb-release ]; then # There is one last test running on 16.04 because of the broken # overlayfs in 18.04. Once that is fixed we can remove the last # 16.04 based test and this if clause. - TRAVIS_PKGS="$TRAVIS_PKGS python-future python-protobuf python-yaml - python-junit.xml python-ipaddress" + CI_PKGS="$CI_PKGS python-future python-protobuf python-yaml + python-junit.xml python-ipaddress" else - TRAVIS_PKGS="$TRAVIS_PKGS python3-future python3-protobuf python3-yaml - python3-junit.xml" + CI_PKGS="$CI_PKGS python3-future python3-protobuf python3-yaml + python3-junit.xml" fi fi @@ -31,11 +31,11 @@ if [ "$UNAME_M" != "x86_64" ]; then # For Travis only x86_64 seems to be baremetal. Other # architectures are running in unprivileged LXD containers. # That seems to block most of CRIU's interfaces. - SKIP_TRAVIS_TEST=1 + SKIP_CI_TEST=1 fi -travis_prep () { - [ -n "$SKIP_TRAVIS_PREP" ] && return +ci_prep () { + [ -n "$SKIP_CI_PREP" ] && return cd ../../ @@ -50,13 +50,13 @@ travis_prep () { CC=gcc # clang support if [ "$CLANG" = "1" ]; then - TRAVIS_PKGS="$TRAVIS_PKGS clang" + CI_PKGS="$CI_PKGS clang" CC=clang fi [ -n "$GCOV" ] && { apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - scripts/travis/apt-install --no-install-suggests g++-7 + scripts/ci/apt-install --no-install-suggests g++-7 CC=gcc-7 } @@ -72,10 +72,10 @@ travis_prep () { # Do not install x86_64 specific packages on other architectures if [ "$UNAME_M" = "x86_64" ]; then - TRAVIS_PKGS="$TRAVIS_PKGS $X86_64_PKGS" + CI_PKGS="$CI_PKGS $X86_64_PKGS" fi - scripts/travis/apt-install "$TRAVIS_PKGS" + scripts/ci/apt-install "$CI_PKGS" chmod a+x "$HOME" # zdtm uses an unversioned python binary to run the tests. @@ -91,7 +91,7 @@ test_stream() { ./test/zdtm.py run --stream -p 2 --keep-going -T "$STREAM_TEST_PATTERN" $ZDTM_OPTS } -travis_prep +ci_prep export GCOV $CC --version @@ -107,7 +107,7 @@ if [ "$WIDTH" -gt 80 ]; then exit 1 fi -[ -n "$SKIP_TRAVIS_TEST" ] && exit 0 +[ -n "$SKIP_CI_TEST" ] && exit 0 ulimit -c unlimited @@ -133,7 +133,7 @@ if [ "${COMPAT_TEST}x" = "yx" ] ; then done # shellcheck disable=SC2086 apt-get remove $INCOMPATIBLE_LIBS - scripts/travis/apt-install "$IA32_PKGS" + scripts/ci/apt-install "$IA32_PKGS" mkdir -p /usr/lib/x86_64-linux-gnu/ mv "$REFUGE"/* /usr/lib/x86_64-linux-gnu/ fi diff --git a/scripts/travis/vagrant.sh b/scripts/ci/vagrant.sh similarity index 100% rename from scripts/travis/vagrant.sh rename to scripts/ci/vagrant.sh From 50878f4f7a003af4d0574ec12d98b1ba20481757 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 3 Nov 2020 11:09:38 +0000 Subject: [PATCH 031/204] CI: distribute CI jobs between CI systems Move podman, openj9, x86_64 tests from Travis to GitHub Actions. Signed-off-by: Adrian Reber --- .github/workflows/openj9-test.yml | 11 +++++++++++ .github/workflows/podman-test.yml | 11 +++++++++++ .github/workflows/x86-64-clang-test.yml | 11 +++++++++++ .github/workflows/x86-64-gcc-test.yml | 11 +++++++++++ .travis.yml | 7 ------- scripts/build/Dockerfile.tmpl | 2 ++ scripts/build/Dockerfile.x86_64.hdr | 2 +- scripts/ci/podman-test.sh | 14 +++++++++++--- 8 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/openj9-test.yml create mode 100644 .github/workflows/podman-test.yml create mode 100644 .github/workflows/x86-64-clang-test.yml create mode 100644 .github/workflows/x86-64-gcc-test.yml diff --git a/.github/workflows/openj9-test.yml b/.github/workflows/openj9-test.yml new file mode 100644 index 0000000000..1d7a1eb6b7 --- /dev/null +++ b/.github/workflows/openj9-test.yml @@ -0,0 +1,11 @@ +name: OpenJ9 Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Run OpenJ9 Test + run: sudo make -C scripts/ci openj9-test diff --git a/.github/workflows/podman-test.yml b/.github/workflows/podman-test.yml new file mode 100644 index 0000000000..447cbf0b69 --- /dev/null +++ b/.github/workflows/podman-test.yml @@ -0,0 +1,11 @@ +name: Podman Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Run Podman Test + run: sudo make -C scripts/ci podman-test diff --git a/.github/workflows/x86-64-clang-test.yml b/.github/workflows/x86-64-clang-test.yml new file mode 100644 index 0000000000..e6e84ef524 --- /dev/null +++ b/.github/workflows/x86-64-clang-test.yml @@ -0,0 +1,11 @@ +name: X86_64 CLANG Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Run X86_64 CLANG Test + run: sudo make -C scripts/ci x86_64 CLANG=1 diff --git a/.github/workflows/x86-64-gcc-test.yml b/.github/workflows/x86-64-gcc-test.yml new file mode 100644 index 0000000000..b8b81ef15b --- /dev/null +++ b/.github/workflows/x86-64-gcc-test.yml @@ -0,0 +1,11 @@ +name: X86_64 GCC Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Run X86_64 GCC Test + run: sudo make -C scripts/ci x86_64 diff --git a/.travis.yml b/.travis.yml index d6ee9a3990..fc95844b3d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,6 @@ env: - TR_ARCH=local CLANG=1 - TR_ARCH=local COMPAT_TEST=y - TR_ARCH=local CLANG=1 COMPAT_TEST=y - - TR_ARCH=x86_64 - - TR_ARCH=x86_64 CLANG=1 - - TR_ARCH=openj9-test - TR_ARCH=vagrant-fedora-no-vdso jobs: include: @@ -57,10 +54,6 @@ jobs: arch: amd64 env: TR_ARCH=fedora-rawhide dist: bionic - - os: linux - arch: amd64 - env: TR_ARCH=podman-test - dist: bionic - os: linux arch: amd64 env: TR_ARCH=docker-test diff --git a/scripts/build/Dockerfile.tmpl b/scripts/build/Dockerfile.tmpl index 2e02d902cc..0cb6de3db5 100644 --- a/scripts/build/Dockerfile.tmpl +++ b/scripts/build/Dockerfile.tmpl @@ -13,9 +13,11 @@ RUN apt-install \ git-core \ iptables \ libaio-dev \ + libbsd-dev \ libcap-dev \ libgnutls28-dev \ libgnutls30 \ + libnftables-dev \ libnl-3-dev \ libprotobuf-c-dev \ libprotobuf-dev \ diff --git a/scripts/build/Dockerfile.x86_64.hdr b/scripts/build/Dockerfile.x86_64.hdr index 7e93c8cc43..32fc2978a5 100644 --- a/scripts/build/Dockerfile.x86_64.hdr +++ b/scripts/build/Dockerfile.x86_64.hdr @@ -1,4 +1,4 @@ -FROM ubuntu:xenial +FROM ubuntu:focal COPY scripts/ci/apt-install /bin/apt-install diff --git a/scripts/ci/podman-test.sh b/scripts/ci/podman-test.sh index f56d10a74f..d61e2d0b8d 100755 --- a/scripts/ci/podman-test.sh +++ b/scripts/ci/podman-test.sh @@ -1,13 +1,21 @@ #!/bin/bash set -x -e -o pipefail -echo 'deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list +if [ ! -e /etc/lsb-release ]; then + # This expects to run on Ubuntu + exit 1 +fi -wget -nv https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_18.04/Release.key -O- | apt-key add - +#shellcheck disable=SC1091 +. /etc/lsb-release + +echo "deb http://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_${DISTRIB_RELEASE}/ /" > /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list + +curl -sL "https://download.opensuse.org/repositories/devel:kubic:libcontainers:stable/xUbuntu_${DISTRIB_RELEASE}/Release.key" | apt-key add - # podman conflicts with a man page from docker-ce # this is a podman packaging bug (https://github.com/containers/libpod/issues/4747) -apt-get -y purge docker-ce +apt-get -y purge docker-ce || : ./apt-install \ apt-transport-https \ From 8722bf012c6c1aab2c6e5983fbf6d089bae1caf2 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sat, 7 Nov 2020 13:22:20 +0000 Subject: [PATCH 032/204] ci: 'fix' lazy tests Most (all?) lazy tests are not being executed if "$KERN_MAJ" -ge "4" and "$KERN_MIN" -ge "18". Currently most CI systems are running on something with 5.4.x which means $KERN_MAJ is greater than 4 but $KERN_MIN is less than 18 and so we are not running any lazy tests. This commit removes the complete lazy test kernel version detection as kernels on the CI systems are new enough to always have all required features. Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index fab392ff24..063921c6e6 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -172,23 +172,17 @@ fi # shellcheck disable=SC2086 ./test/zdtm.py run -a -p 2 --keep-going $ZDTM_OPTS -KERN_MAJ=$(uname -r | cut -d. -f1) -KERN_MIN=$(uname -r | cut -d. -f2) -if [ "$KERN_MAJ" -ge "4" ] && [ "$KERN_MIN" -ge "18" ]; then - LAZY_EXCLUDE="-x cmdlinenv00 -x maps007" -else - LAZY_EXCLUDE="-x maps007 -x fork -x fork2 -x uffd-events -x cgroupns - -x socket_listen -x socket_listen6 -x cmdlinenv00 - -x socket_close_data01 -x file_read -x lazy-thp -x futex" -fi -LAZY_EXCLUDE="$LAZY_EXCLUDE -x maps04" +LAZY_EXCLUDE="-x maps04 -x cmdlinenv00 -x maps007" LAZY_TESTS='.*\(maps0\|uffd-events\|lazy-thp\|futex\|fork\).*' LAZY_OPTS="-p 2 -T $LAZY_TESTS $LAZY_EXCLUDE $ZDTM_OPTS" -./test/zdtm.py run "$LAZY_OPTS" --lazy-pages -./test/zdtm.py run "$LAZY_OPTS" --remote-lazy-pages -./test/zdtm.py run "$LAZY_OPTS" --remote-lazy-pages --tls +# shellcheck disable=SC2086 +./test/zdtm.py run $LAZY_OPTS --lazy-pages +# shellcheck disable=SC2086 +./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages +# shellcheck disable=SC2086 +./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages --tls bash ./test/jenkins/criu-fault.sh bash ./test/jenkins/criu-fcg.sh From 953e87c7b4aed8c92634d488eb8b5e9d2bde95a8 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Sun, 8 Nov 2020 09:50:23 +0200 Subject: [PATCH 033/204] ci: fix lazy-pages test selection The special characters in the test selection regexp should no be esaped for the regexp to work properly. Signed-off-by: Mike Rapoport --- scripts/ci/run-ci-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 063921c6e6..29a0524d2e 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -174,7 +174,7 @@ fi LAZY_EXCLUDE="-x maps04 -x cmdlinenv00 -x maps007" -LAZY_TESTS='.*\(maps0\|uffd-events\|lazy-thp\|futex\|fork\).*' +LAZY_TESTS='.*(maps0|uffd-events|lazy-thp|futex|fork).*' LAZY_OPTS="-p 2 -T $LAZY_TESTS $LAZY_EXCLUDE $ZDTM_OPTS" # shellcheck disable=SC2086 From 68585dec91dfc74e90615c40dd2a07ee0f78494e Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sat, 7 Nov 2020 19:14:10 +0000 Subject: [PATCH 034/204] criu-ns: Remove unreachable statement Raising an exception breaks out of the normal flow of control of a code block. When an exception is not handled, the interpreter terminates execution of the program, or returns to its interactive main loop. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index dc6da84012..05635b1605 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -81,7 +81,6 @@ def wrap_restore(): # Spawn CRIU binary run_criu() raise OSError(errno.ENOENT, "No such command") - sys.exit(0) # Wait for CRIU to exit and report the status back while True: From 369e17b293378e93514b8eb922e39da1ce1c4e76 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 30 Sep 2020 13:08:02 +0000 Subject: [PATCH 035/204] travis: rename centos test to centos7 Because it is actually running on CentOS 7 and to easier distinguish it from the new CentOS 8 test. Signed-off-by: Adrian Reber --- .travis.yml | 2 +- scripts/build/{Dockerfile.centos => Dockerfile.centos7} | 0 scripts/build/Makefile | 2 +- scripts/ci/Makefile | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename scripts/build/{Dockerfile.centos => Dockerfile.centos7} (100%) diff --git a/.travis.yml b/.travis.yml index fc95844b3d..da4c85c4ef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -74,7 +74,7 @@ jobs: dist: bionic - os: linux arch: amd64 - env: TR_ARCH=centos + env: TR_ARCH=centos7 dist: bionic - os: linux arch: amd64 diff --git a/scripts/build/Dockerfile.centos b/scripts/build/Dockerfile.centos7 similarity index 100% rename from scripts/build/Dockerfile.centos rename to scripts/build/Dockerfile.centos7 diff --git a/scripts/build/Makefile b/scripts/build/Makefile index 974d1455f4..0fe4663032 100644 --- a/scripts/build/Makefile +++ b/scripts/build/Makefile @@ -1,4 +1,4 @@ -ARCHES := x86_64 fedora-asan fedora-rawhide centos armv7hf +ARCHES := x86_64 fedora-asan fedora-rawhide centos7 armv7hf TARGETS := $(ARCHES) alpine TARGETS_CLANG := $(addsuffix $(TARGETS),-clang) CONTAINER_RUNTIME := docker diff --git a/scripts/ci/Makefile b/scripts/ci/Makefile index 513d58bfb3..098ed1e14b 100644 --- a/scripts/ci/Makefile +++ b/scripts/ci/Makefile @@ -11,7 +11,7 @@ ifdef CLANG target-suffix = -clang endif -TARGETS := alpine fedora-rawhide centos +TARGETS := alpine fedora-rawhide centos7 ZDTM_OPTIONS := UNAME := $(shell uname -m) From 407404297e886f170eabd3032af86636142744c6 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sat, 7 Nov 2020 12:40:22 +0000 Subject: [PATCH 036/204] ci: switch centos7 to github actions Signed-off-by: Adrian Reber --- .github/workflows/centos-test.yml | 15 +++++++++++++++ scripts/ci/Makefile | 12 +++++++++++- scripts/ci/run-ci-tests.sh | 8 +++++--- 3 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/centos-test.yml diff --git a/.github/workflows/centos-test.yml b/.github/workflows/centos-test.yml new file mode 100644 index 0000000000..41b1f3a6ea --- /dev/null +++ b/.github/workflows/centos-test.yml @@ -0,0 +1,15 @@ +name: CentOS Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + target: [centos7] + + steps: + - uses: actions/checkout@v2 + - name: Run CentOS ${{ matrix.target }} Test + run: sudo -E make -C scripts/ci ${{ matrix.target }} diff --git a/scripts/ci/Makefile b/scripts/ci/Makefile index 098ed1e14b..b75314a0a3 100644 --- a/scripts/ci/Makefile +++ b/scripts/ci/Makefile @@ -27,10 +27,20 @@ endef export DOCKER_JSON +ifeq ($(GITHUB_ACTIONS),true) + # GitHub Actions does not give us a real TTY and errors out with + # 'the input device is not a TTY' if using '-t' + CONTAINER_TERMINAL := -i +else + CONTAINER_TERMINAL := -it +endif + +export CONTAINER_TERMINAL + ifeq ($(UNAME),x86_64) # On anything besides x86_64 Travis is running unprivileged LXD # containers which do not support running docker with '--privileged'. - CONTAINER_OPTS := --rm -it --privileged -v /lib/modules:/lib/modules --tmpfs /run + CONTAINER_OPTS := --rm $(CONTAINER_TERMINAL) --privileged -v /lib/modules:/lib/modules --tmpfs /run else CONTAINER_OPTS := --rm -v /lib/modules:/lib/modules --tmpfs /run endif diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 29a0524d2e..e470bf62aa 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -193,7 +193,11 @@ if [ -z "$SKIP_EXT_DEV_TEST" ]; then fi #make -C test/others/exec/ run make -C test/others/make/ run CC="$CC" -make -C test/others/shell-job/ run +if [ -n "$TRAVIS" ]; then + # GitHub Actions does not provide a real TTY and CRIU will fail with: + # Error (criu/tty.c:1014): tty: Don't have tty to inherit session from, aborting + make -C test/others/shell-job/ run +fi make -C test/others/rpc/ run ./test/zdtm.py run -t zdtm/static/env00 --sibling @@ -223,5 +227,3 @@ make -C test/others/libcriu run # external namespace testing make -C test/others/ns_ext run - -make -C test/others/shell-job From ffac3d649da087b65729ee6dcbe3cf05ab6faa86 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 28 Sep 2020 16:34:24 +0000 Subject: [PATCH 037/204] ci: add CentOS 8 based CI run Our CentOS based CI run is based on CentOS 7. CentOS 8 exists already for some time and CentOS 7 will probably go end of life at some point. This adds a CentOS 8 based CI run to be prepared for the time CentOS 7 goes away. Signed-off-by: Adrian Reber --- .github/workflows/centos-test.yml | 2 +- scripts/build/Dockerfile.centos8 | 56 +++++++++++++++++++++++++++++++ scripts/build/Makefile | 2 +- scripts/ci/Makefile | 2 +- 4 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 scripts/build/Dockerfile.centos8 diff --git a/.github/workflows/centos-test.yml b/.github/workflows/centos-test.yml index 41b1f3a6ea..e14c2460b2 100644 --- a/.github/workflows/centos-test.yml +++ b/.github/workflows/centos-test.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - target: [centos7] + target: [centos7, centos8] steps: - uses: actions/checkout@v2 diff --git a/scripts/build/Dockerfile.centos8 b/scripts/build/Dockerfile.centos8 new file mode 100644 index 0000000000..0b658d5fa3 --- /dev/null +++ b/scripts/build/Dockerfile.centos8 @@ -0,0 +1,56 @@ +FROM registry.centos.org/centos/centos:8 + +ARG CC=gcc +ARG ENV1=FOOBAR + +RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm dnf-plugins-core +RUN yum config-manager --set-enabled PowerTools +RUN yum install -y --allowerasing \ + asciidoc \ + ccache \ + coreutils \ + chkconfig \ + diffutils \ + findutils \ + gcc \ + git \ + gnutls-devel \ + iproute \ + iptables \ + libaio-devel \ + libasan \ + libcap-devel \ + libnet-devel \ + libnl3-devel \ + libselinux-devel \ + make \ + procps-ng \ + protobuf-c-devel \ + protobuf-devel \ + python3-devel \ + python3-flake8 \ + python3-PyYAML \ + python3-future \ + python3-protobuf \ + python3-pip \ + sudo \ + tar \ + which \ + xmlto + +RUN alternatives --set python /usr/bin/python3 +ENV PYTHON=python3 + +COPY . /criu +WORKDIR /criu + +ENV CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes +RUN mv .ccache /tmp && make mrproper && ccache -sz && \ + date && make -j $(nproc) CC="$CC" && date && ccache -s + +# The rpc test cases are running as user #1000, let's add the user +RUN adduser -u 1000 test + +RUN pip3 install junit_xml + +RUN make -C test/zdtm -j $(nproc) diff --git a/scripts/build/Makefile b/scripts/build/Makefile index 0fe4663032..85bbf2010c 100644 --- a/scripts/build/Makefile +++ b/scripts/build/Makefile @@ -1,4 +1,4 @@ -ARCHES := x86_64 fedora-asan fedora-rawhide centos7 armv7hf +ARCHES := x86_64 fedora-asan fedora-rawhide centos7 armv7hf centos8 TARGETS := $(ARCHES) alpine TARGETS_CLANG := $(addsuffix $(TARGETS),-clang) CONTAINER_RUNTIME := docker diff --git a/scripts/ci/Makefile b/scripts/ci/Makefile index b75314a0a3..ffa78446a2 100644 --- a/scripts/ci/Makefile +++ b/scripts/ci/Makefile @@ -11,7 +11,7 @@ ifdef CLANG target-suffix = -clang endif -TARGETS := alpine fedora-rawhide centos7 +TARGETS := alpine fedora-rawhide centos7 centos8 ZDTM_OPTIONS := UNAME := $(shell uname -m) From 7e1f22b78f158c5801b5d4323a9c06fbdac9f082 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sun, 8 Nov 2020 11:54:20 +0000 Subject: [PATCH 038/204] uffd: fix 'double free detected in tcache 2' One of the previous static code analyzer fixes added a xfree() at the end of cr_lazy_pages(). It can, however, happen that during complete_forks() the memory location for events is moved by xrealloc() and the final xfree() will be done on the wrong address. Passing &events to handle_requests() enables the xfree() to free the correct and changed memory location. Signed-off-by: Adrian Reber --- criu/uffd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/criu/uffd.c b/criu/uffd.c index a6886ca108..958edab2fc 100644 --- a/criu/uffd.c +++ b/criu/uffd.c @@ -1254,18 +1254,18 @@ static void lazy_pages_summary(struct lazy_pages_info *lpi) #endif } -static int handle_requests(int epollfd, struct epoll_event *events, int nr_fds) +static int handle_requests(int epollfd, struct epoll_event **events, int nr_fds) { struct lazy_pages_info *lpi, *n; int poll_timeout = -1; int ret; for (;;) { - ret = epoll_run_rfds(epollfd, events, nr_fds, poll_timeout); + ret = epoll_run_rfds(epollfd, *events, nr_fds, poll_timeout); if (ret < 0) goto out; if (ret > 0) { - ret = complete_forks(epollfd, &events, &nr_fds); + ret = complete_forks(epollfd, events, &nr_fds); if (ret < 0) goto out; if (restore_finished) @@ -1481,7 +1481,7 @@ int cr_lazy_pages(bool daemon) } } - ret = handle_requests(epollfd, events, nr_fds); + ret = handle_requests(epollfd, &events, nr_fds); tls_terminate_session(); From ab288c35cb3ac4988151bcec61d44f54a8052dd7 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 12 Nov 2020 11:17:01 +0000 Subject: [PATCH 039/204] uffd: handle xrealloc() failure In the case, that xrealloc() fails do not overwrite the original pointer to be able to free the original pointer on exit. Signed-off-by: Adrian Reber --- criu/uffd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/criu/uffd.c b/criu/uffd.c index 958edab2fc..96586ad199 100644 --- a/criu/uffd.c +++ b/criu/uffd.c @@ -1131,6 +1131,7 @@ static int handle_fork(struct lazy_pages_info *parent_lpi, struct uffd_msg *msg) static int complete_forks(int epollfd, struct epoll_event **events, int *nr_fds) { struct lazy_pages_info *lpi, *n; + struct epoll_event *tmp; if (list_empty(&pending_lpis)) return 1; @@ -1138,9 +1139,10 @@ static int complete_forks(int epollfd, struct epoll_event **events, int *nr_fds) list_for_each_entry(lpi, &pending_lpis, l) (*nr_fds)++; - *events = xrealloc(*events, sizeof(struct epoll_event) * (*nr_fds)); - if (!*events) + tmp = xrealloc(*events, sizeof(struct epoll_event) * (*nr_fds)); + if (!tmp) return -1; + *events = tmp; list_for_each_entry_safe(lpi, n, &pending_lpis, l) { if (epoll_add_rfd(epollfd, &lpi->lpfd)) From 403741feb36938f1de952f898a4645d78dc5f26b Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Wed, 11 Nov 2020 20:01:03 +0000 Subject: [PATCH 040/204] vdso: Let zero-terminator in vdso_symbol_length When vdso symbol is copied, it should be zero-terminated. The logging code wants to print vdso names that differ between vdso from images and vdso that's provided by kernel: : pr_info("[%zu]`%s` offset differs: %lx != %lx (rt)\n", : i, sym_name, sym_offset, rt_sym_offset); In unlikely event when vdso function name is longer than 32 (not any currently), null-terminator is missing. Signed-off-by: Dmitry Safonov --- criu/pie/util-vdso.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/criu/pie/util-vdso.c b/criu/pie/util-vdso.c index 58b27680c8..ff91a3b12f 100644 --- a/criu/pie/util-vdso.c +++ b/criu/pie/util-vdso.c @@ -222,7 +222,7 @@ static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load, const char *vdso_symbols[VDSO_SYMBOL_MAX] = { ARCH_VDSO_SYMBOLS }; - const size_t vdso_symbol_length = sizeof(t->symbols[0].name); + const size_t vdso_symbol_length = sizeof(t->symbols[0].name) - 1; Hash_t nbucket, nchain; Hash_t *bucket, *chain; @@ -265,6 +265,7 @@ static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load, if (std_strncmp(name, symbol, vdso_symbol_length)) continue; + /* XXX: provide strncpy() implementation for PIE */ memcpy(t->symbols[i].name, name, vdso_symbol_length); t->symbols[i].offset = (unsigned long)sym->st_value - load->p_vaddr; break; From 56d3eab1cbfbf16d7904778db7736feb9ed54ea0 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Wed, 11 Nov 2020 23:14:39 +0000 Subject: [PATCH 041/204] compel/log: Stop parsing at unknown format specifier Currently if the specifier can't be parsed - error message is printed and parsing of the format string continues. That's wrong as the argument for the specifier will be used for the next specifier. I.e: pr_info("[%zu]`%s`\n", 0UL, "") will crash PIE because %u is not known and the argument (0UL) will be used for dereferencing string for %s. Stop parsing printf position arguments at an unknown specifier. Make this string visible so that `grep Error` in zdtm.py will catch it: =[log]=> dump/zdtm/static/busyloop00/52/1/restore.log ------------------------ grep Error ------------------------ b'(00.001847) pie: 52: vdso: [' b'Error: Unknown printf format %u' ------------------------ ERROR OVER ------------------------ Send the 15 signal to 52 Wait for zdtm/static/busyloop00(52) to die for 0.100000 ======================= Test zdtm/static/busyloop00 PASS ======================= Reported-by: @ashwani29 Signed-off-by: Dmitry Safonov --- compel/plugins/std/log.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/compel/plugins/std/log.c b/compel/plugins/std/log.c index f9be432ea8..3fb66c2cd8 100644 --- a/compel/plugins/std/log.c +++ b/compel/plugins/std/log.c @@ -330,9 +330,10 @@ static void sbuf_printf(struct simple_buf *b, const char *format, va_list args) print_hex_l((unsigned long)va_arg(args, void *), b); break; default: - print_string("UNKNOWN FORMAT ", b); + print_string("\nError: Unknown printf format %", b); sbuf_putc(b, *s); - break; + sbuf_putc(b, '\n'); + return; } s++; } From 0ecec9966c15ad11d8557a36452f9b8648554e39 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 12 Nov 2020 00:26:11 +0000 Subject: [PATCH 042/204] compel/log: Provide %u specifier parsing %u is quite common and I remember there were workarounds to print (unsigned long) as long or whatever. Just support it from now - it's not hard and not much code. Signed-off-by: Dmitry Safonov --- compel/plugins/std/log.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/compel/plugins/std/log.c b/compel/plugins/std/log.c index 3fb66c2cd8..0053482467 100644 --- a/compel/plugins/std/log.c +++ b/compel/plugins/std/log.c @@ -225,6 +225,22 @@ static void print_num_l(long num, struct simple_buf *b) print_string(s, b); } +static void print_num_u(unsigned long num, struct simple_buf *b) +{ + char buf[22], *s; + + buf[21] = '\0'; + s = &buf[21]; + + do { + s--; + *s = (num % 10) + '0'; + num /= 10; + } while (num > 0); + + print_string(s, b); +} + static void hexdigit(unsigned int v, char *to, char **z) { *to = "0123456789abcdef"[v & 0xf]; @@ -329,6 +345,12 @@ static void sbuf_printf(struct simple_buf *b, const char *format, va_list args) case 'p': print_hex_l((unsigned long)va_arg(args, void *), b); break; + case 'u': + if (along) + print_num_u(va_arg(args, unsigned long), b); + else + print_num_u(va_arg(args, unsigned), b); + break; default: print_string("\nError: Unknown printf format %", b); sbuf_putc(b, *s); From 42a86db74b4b5a15d2d1ea83f5aeea31d4b244ba Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Fri, 20 Nov 2020 20:44:59 +0000 Subject: [PATCH 043/204] tls: Add logging within send/recv callbacks Log messages showing the send/recv errno value would help us to debug issues such as #1280. Example: Error (criu/tls.c:321): tls: Pull callback recv failed: Connection reset by peer' Error (criu/tls.c:147): tls: Failed receiving data: Error in the pull function.' Error (criu/page-xfer.c:1225): page-xfer: Can't read pagemap from socket: I/O error" Signed-off-by: Radostin Stoyanov --- criu/tls.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/criu/tls.c b/criu/tls.c index f7b94dee8c..e865368c4c 100644 --- a/criu/tls.c +++ b/criu/tls.c @@ -303,13 +303,25 @@ static int tls_x509_setup_creds(void) static ssize_t _tls_push_cb(void *p, const void* data, size_t sz) { int fd = *(int *)(p); - return send(fd, data, sz, tls_sk_flags); + int ret = send(fd, data, sz, tls_sk_flags); + if (ret < 0 && errno != EAGAIN) { + int _errno = errno; + pr_perror("Push callback send failed"); + errno = _errno; + } + return ret; } static ssize_t _tls_pull_cb(void *p, void* data, size_t sz) { int fd = *(int *)(p); - return recv(fd, data, sz, tls_sk_flags); + int ret = recv(fd, data, sz, tls_sk_flags); + if (ret < 0 && errno != EAGAIN) { + int _errno = errno; + pr_perror("Pull callback recv failed"); + errno = _errno; + } + return ret; } static int tls_x509_setup_session(unsigned int flags) From 3cf87ed48527b3013319ec7047f9c68e83df3fd3 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 4 Nov 2020 07:51:32 +0000 Subject: [PATCH 044/204] ci: use graviton2 for arm64 tests on Travis Using travis-ci.com instead of travis-ci.org offers access to bare metal aarch64 based systems and thus enabling us to run the full CRIU CI test suite. Switch arm64 based tests to arm64-graviton2 for tests. This is the first non x86_64 architecture running tests and not just compile in Travis. Signed-off-by: Adrian Reber --- .travis.yml | 14 +++++++---- scripts/ci/run-ci-tests.sh | 23 ++++++++++++++----- test/others/libcriu/run.sh | 5 +++- test/zdtm/static/netns-nf.desc | 2 +- .../static/socket-tcp-closed-last-ack.desc | 4 ++-- test/zdtm/static/socket-tcp-reseted.desc | 6 ++--- test/zdtm/static/socket-tcp-syn-sent.desc | 4 ++-- 7 files changed, 38 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index da4c85c4ef..1c6da2a8ab 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,12 +29,16 @@ jobs: env: TR_ARCH=local dist: bionic - os: linux - arch: arm64 - env: TR_ARCH=local - dist: bionic + arch: arm64-graviton2 + env: TR_ARCH=local RUN_TESTS=1 + dist: focal + group: edge + virt: vm - os: linux - arch: arm64 - env: TR_ARCH=local CLANG=1 + arch: arm64-graviton2 + env: TR_ARCH=local CLANG=1 RUN_TESTS=1 + group: edge + virt: vm dist: bionic - os: linux arch: arm64 diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index e470bf62aa..648d5886c3 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -31,7 +31,11 @@ if [ "$UNAME_M" != "x86_64" ]; then # For Travis only x86_64 seems to be baremetal. Other # architectures are running in unprivileged LXD containers. # That seems to block most of CRIU's interfaces. - SKIP_CI_TEST=1 + + # But with the introduction of baremetal aarch64 systems in + # Travis (arch: arm64-graviton2) we can override this using + # an evironment variable + [ -n "$RUN_TESTS" ] || SKIP_CI_TEST=1 fi ci_prep () { @@ -147,8 +151,11 @@ time make CC="$CC" -j4 -C test/zdtm umask 0000 ./criu/criu check ./criu/criu check --all || echo $? -./criu/criu cpuinfo dump -./criu/criu cpuinfo check +if [ "$UNAME_M" == "x86_64" ]; then + # This fails on aarch64 (aws-graviton2) + ./criu/criu cpuinfo dump + ./criu/criu cpuinfo check +fi export SKIP_PREP=1 # The 3.19 kernel (from Ubuntu 14.04) has a bug. When /proc/PID/pagemap @@ -184,9 +191,13 @@ LAZY_OPTS="-p 2 -T $LAZY_TESTS $LAZY_EXCLUDE $ZDTM_OPTS" # shellcheck disable=SC2086 ./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages --tls -bash ./test/jenkins/criu-fault.sh -bash ./test/jenkins/criu-fcg.sh -bash ./test/jenkins/criu-inhfd.sh +bash -x ./test/jenkins/criu-fault.sh +if [ "$UNAME_M" == "x86_64" ]; then + # This fails on aarch64 (aws-graviton2) with: + # 33: ERR: thread-bomb.c:49: pthread_attr_setstacksize(): 22 + bash -x ./test/jenkins/criu-fcg.sh +fi +bash -x ./test/jenkins/criu-inhfd.sh if [ -z "$SKIP_EXT_DEV_TEST" ]; then make -C test/others/mnt-ext-dev/ run diff --git a/test/others/libcriu/run.sh b/test/others/libcriu/run.sh index bd92f8544b..5a0dca46be 100755 --- a/test/others/libcriu/run.sh +++ b/test/others/libcriu/run.sh @@ -48,7 +48,10 @@ function run_test { run_test test_sub run_test test_self run_test test_notify -run_test test_iters +if [ "$(uname -m)" == "x86_64" ]; then + # Skip this on aarch64 as aarch64 has no dirty page tracking + run_test test_iters +fi run_test test_errno echo "== Tests done" diff --git a/test/zdtm/static/netns-nf.desc b/test/zdtm/static/netns-nf.desc index 496477aa7a..8fd3770bd4 100644 --- a/test/zdtm/static/netns-nf.desc +++ b/test/zdtm/static/netns-nf.desc @@ -1,6 +1,6 @@ { 'deps': [ '/bin/sh', '/sbin/iptables', - '/usr/lib64/xtables/libxt_standard.so|/usr/lib/iptables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so', + '/usr/lib64/xtables/libxt_standard.so|/usr/lib/iptables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', '/usr/bin/diff'], 'flags': 'suid', 'flavor': 'ns uns'} diff --git a/test/zdtm/static/socket-tcp-closed-last-ack.desc b/test/zdtm/static/socket-tcp-closed-last-ack.desc index 8a9df7fc40..43afd920eb 100644 --- a/test/zdtm/static/socket-tcp-closed-last-ack.desc +++ b/test/zdtm/static/socket-tcp-closed-last-ack.desc @@ -1,7 +1,7 @@ { 'deps': [ '/bin/sh', '/sbin/iptables', - '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so', - '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so', + '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_tcp.so', + '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', ], 'opts': '--tcp-established', 'flags': 'suid nouser samens', diff --git a/test/zdtm/static/socket-tcp-reseted.desc b/test/zdtm/static/socket-tcp-reseted.desc index 94425b44e7..744ed88c96 100644 --- a/test/zdtm/static/socket-tcp-reseted.desc +++ b/test/zdtm/static/socket-tcp-reseted.desc @@ -1,8 +1,8 @@ { 'deps': [ '/bin/sh', '/sbin/iptables', - '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so', - '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so', - '/usr/lib64/xtables/libipt_REJECT.so|/lib/xtables/libipt_REJECT.so|/usr/lib/powerpc64le-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/x86_64-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/xtables/libipt_REJECT.so|/usr/lib/s390x-linux-gnu/xtables/libipt_REJECT.so', + '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_tcp.so', + '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', + '/usr/lib64/xtables/libipt_REJECT.so|/lib/xtables/libipt_REJECT.so|/usr/lib/powerpc64le-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/x86_64-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/xtables/libipt_REJECT.so|/usr/lib/s390x-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/aarch64-linux-gnu/xtables/libipt_REJECT.so', ], 'opts': '--tcp-established', 'flags': 'suid nouser samens', diff --git a/test/zdtm/static/socket-tcp-syn-sent.desc b/test/zdtm/static/socket-tcp-syn-sent.desc index b9f3d5e6db..a276736812 100644 --- a/test/zdtm/static/socket-tcp-syn-sent.desc +++ b/test/zdtm/static/socket-tcp-syn-sent.desc @@ -1,7 +1,7 @@ { 'deps': [ '/bin/sh', '/sbin/iptables', - '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so', - '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so', + '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_tcp.so', + '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', ], 'opts': '--tcp-established', 'flags': 'suid nouser samens', From 430e464c75598352009e88cf837d8f38874c5c6e Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 12 Nov 2020 17:53:00 +0000 Subject: [PATCH 045/204] CI: remove centos7 from Travis It is running on GitHub Actions Signed-off-by: Adrian Reber --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1c6da2a8ab..a82ed910ca 100644 --- a/.travis.yml +++ b/.travis.yml @@ -76,10 +76,6 @@ jobs: arch: amd64 env: TR_ARCH=alpine dist: bionic - - os: linux - arch: amd64 - env: TR_ARCH=centos7 - dist: bionic - os: linux arch: amd64 env: TR_ARCH=fedora-asan From a813f86767760abd75f708becc0be6dc3359de45 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 12 Nov 2020 11:07:18 +0000 Subject: [PATCH 046/204] ci: remove special handling for mips For the schedule daily special definitions were needed for MIPS as it is not part of the release branch. Now that the release branch contains MIPS, it is no longer necessary to have separate files for MIPS. This also changes to make the scheduled runs actually daily and not hourly. Signed-off-by: Adrian Reber --- .../workflows/cross-compile-daily-mips.yml | 22 ------------------- .github/workflows/cross-compile-daily.yml | 4 ++-- .github/workflows/cross-compile-mips.yml | 21 ------------------ .github/workflows/cross-compile.yml | 2 +- 4 files changed, 3 insertions(+), 46 deletions(-) delete mode 100644 .github/workflows/cross-compile-daily-mips.yml delete mode 100644 .github/workflows/cross-compile-mips.yml diff --git a/.github/workflows/cross-compile-daily-mips.yml b/.github/workflows/cross-compile-daily-mips.yml deleted file mode 100644 index 164f09c99b..0000000000 --- a/.github/workflows/cross-compile-daily-mips.yml +++ /dev/null @@ -1,22 +0,0 @@ -name: Daily Cross Compile Tests - -on: - schedule: - - cron: '30 * * * *' - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - matrix: - target: [mips64el-cross] - branches: [criu-dev] - - steps: - - uses: actions/checkout@v2 - with: - ref: ${{ matrix.branches }} - - name: Run Cross Compilation Targets - run: > - sudo make -C scripts/ci ${{ matrix.target }} diff --git a/.github/workflows/cross-compile-daily.yml b/.github/workflows/cross-compile-daily.yml index aed08f2c98..7012132766 100644 --- a/.github/workflows/cross-compile-daily.yml +++ b/.github/workflows/cross-compile-daily.yml @@ -2,7 +2,7 @@ name: Daily Cross Compile Tests on: schedule: - - cron: '30 * * * *' + - cron: '30 12 * * *' jobs: build: @@ -10,7 +10,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [armv7-cross, aarch64-cross, ppc64-cross] + target: [armv7-cross, aarch64-cross, ppc64-cross, mips64el-cross] branches: [criu-dev, master] steps: diff --git a/.github/workflows/cross-compile-mips.yml b/.github/workflows/cross-compile-mips.yml deleted file mode 100644 index 3b475ff030..0000000000 --- a/.github/workflows/cross-compile-mips.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: Cross Compile Tests - -on: - push: - branches: [criu-dev] - pull_request: - branches: [criu-dev] - -jobs: - build: - - runs-on: ubuntu-latest - strategy: - matrix: - target: [mips64el-cross] - - steps: - - uses: actions/checkout@v2 - - name: Run Cross Compilation Targets - run: > - sudo make -C scripts/ci ${{ matrix.target }} diff --git a/.github/workflows/cross-compile.yml b/.github/workflows/cross-compile.yml index d8143b397e..90862e7abd 100644 --- a/.github/workflows/cross-compile.yml +++ b/.github/workflows/cross-compile.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - target: [armv7-cross, aarch64-cross, ppc64-cross] + target: [armv7-cross, aarch64-cross, ppc64-cross, mips64el-cross] steps: - uses: actions/checkout@v2 From a667d5778e3651cde327db77f326fe3a304e95c6 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Wed, 11 Nov 2020 01:24:48 +0000 Subject: [PATCH 047/204] cr-restore: Properly inspect status in sigchld_process() Currently the code checks for SIGSTOP only if (!current). Let's provide better status checks for debug-ability. Signed-off-by: Dmitry Safonov --- criu/cr-restore.c | 58 +++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index d94db5fd3e..8af2e2974a 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1531,35 +1531,53 @@ static inline int fork_with_pid(struct pstree_item *item) return ret; } -static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) +/* Returns 0 if restore can be continued */ +static int sigchld_process(int status, pid_t pid) { - int status, pid, exit; + int sig; + + if (WIFEXITED(status)) { + pr_err("%d exited, status=%d\n", pid, WEXITSTATUS(status)); + return -1; + } else if (WIFSIGNALED(status)) { + sig = WTERMSIG(status); + pr_err("%d killed by signal %d: %s\n", pid, sig, strsignal(sig)); + return -1; + } else if (WIFSTOPPED(status)) { + sig = WSTOPSIG(status); + /* The root task is ptraced. Allow it to handle SIGCHLD */ + if (sig == SIGCHLD && !current) { + if (ptrace(PTRACE_CONT, pid, 0, SIGCHLD)) { + pr_perror("Unable to resume %d", pid); + return -1; + } + return 0; + } + pr_err("%d stopped by signal %d: %s\n", pid, sig, strsignal(sig)); + return -1; + } else if (WIFCONTINUED(status)) { + pr_err("%d unexpectedly continued\n", pid); + return -1; + } + pr_err("wait for %d resulted in %x status\n", pid, status); + return -1; +} +static void sigchld_handler(int signal, siginfo_t *siginfo, void *data) +{ while (1) { + int status; + pid_t pid; + pid = waitpid(-1, &status, WNOHANG); if (pid <= 0) return; - if (!current && WIFSTOPPED(status) && - WSTOPSIG(status) == SIGCHLD) { - /* The root task is ptraced. Allow it to handle SIGCHLD */ - if (ptrace(PTRACE_CONT, pid, 0, SIGCHLD)) - pr_perror("Unable to resume %d", pid); - return; - } - - exit = WIFEXITED(status); - status = exit ? WEXITSTATUS(status) : WTERMSIG(status); - - break; + if (sigchld_process(status, pid) < 0) + goto err_abort; } - if (exit) - pr_err("%d exited, status=%d\n", pid, status); - else - pr_err("%d killed by signal %d: %s\n", - pid, status, strsignal(status)); - +err_abort: futex_abort_and_wake(&task_entries->nr_in_progress); } From 87d007bcd0a83af4576581bba10e63637cef01e6 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Fri, 20 Nov 2020 11:31:40 +0300 Subject: [PATCH 048/204] uffd: cleanup read error handling in handle_uffd_event We can't use errno in case read returned >=0 according to man. Found in scope of #1277 Signed-off-by: Pavel Tikhomirov --- criu/uffd.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/criu/uffd.c b/criu/uffd.c index 96586ad199..815b848bbe 100644 --- a/criu/uffd.c +++ b/criu/uffd.c @@ -1209,17 +1209,16 @@ static int handle_uffd_event(struct epoll_rfd *lpfd) lpi = container_of(lpfd, struct lazy_pages_info, lpfd); ret = read(lpfd->fd, &msg, sizeof(msg)); - if (!ret) - return 1; - - if (ret != sizeof(msg)) { + if (ret < 0) { /* we've already handled the page fault for another thread */ if (errno == EAGAIN) return 0; - if (ret < 0) - lp_perror(lpi, "Can't read uffd message"); - else - lp_err(lpi, "Can't read uffd message: short read"); + lp_perror(lpi, "Can't read uffd message"); + return -1; + } else if (ret == 0) { + return 1; + } else if (ret != sizeof(msg)) { + lp_err(lpi, "Can't read uffd message: short read"); return -1; } From bc94f35a0b75fa13542558f25d0896b1d1d8b1b9 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Thu, 19 Nov 2020 19:17:35 +0200 Subject: [PATCH 049/204] uffd: check for exited task when reading uffd_msg Sometimes there are uffd messages in a queue of a dying task and by the time these messages are processed in handle_request, the uffd is no longer valid and reading from it causes errors. Add processing of EBADF in handle_uffd_event() to gracefully handle such situation. Signed-off-by: Mike Rapoport --- criu/uffd.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/criu/uffd.c b/criu/uffd.c index 815b848bbe..e460423445 100644 --- a/criu/uffd.c +++ b/criu/uffd.c @@ -1213,6 +1213,10 @@ static int handle_uffd_event(struct epoll_rfd *lpfd) /* we've already handled the page fault for another thread */ if (errno == EAGAIN) return 0; + if (errno == EBADF && lpi->exited) { + lp_debug(lpi, "excess message in queue: %d", msg.event); + return 0; + } lp_perror(lpi, "Can't read uffd message"); return -1; } else if (ret == 0) { From 82f6518db35e392a7d31094b1cca3f19271ea9c2 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Fri, 20 Nov 2020 13:06:13 +0300 Subject: [PATCH 050/204] zdtm: on fail with no error also print the tail of the log We see strange cases there page-server or lazy-pages are exiting with non-zero but print no errors, probably the tail of the log can help us to understand what happened. There are some other uses of grep_errors but let's only change cases where we explicitly through an exeption on bad ret. For others I'm not sure if we need extra output, e.g. for validly failing fault injections. To debug #1280 Signed-off-by: Pavel Tikhomirov --- test/zdtm.py | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/test/zdtm.py b/test/zdtm.py index dff64d4ed5..a33807050f 100755 --- a/test/zdtm.py +++ b/test/zdtm.py @@ -1043,19 +1043,19 @@ def fini(self): ret = self.__dump_process.wait() if self.__lazy_pages_p: ret = self.__lazy_pages_p.wait() - grep_errors(os.path.join(self.__ddir(), "lazy-pages.log")) + grep_errors(os.path.join(self.__ddir(), "lazy-pages.log"), err=ret) self.__lazy_pages_p = None if ret: raise test_fail_exc("criu lazy-pages exited with %s" % ret) if self.__page_server_p: ret = self.__page_server_p.wait() - grep_errors(os.path.join(self.__ddir(), "page-server.log")) + grep_errors(os.path.join(self.__ddir(), "page-server.log"), err=ret) self.__page_server_p = None if ret: raise test_fail_exc("criu page-server exited with %s" % ret) if self.__dump_process: ret = self.__dump_process.wait() - grep_errors(os.path.join(self.__ddir(), "dump.log")) + grep_errors(os.path.join(self.__ddir(), "dump.log"), err=ret) self.__dump_process = None if ret: raise test_fail_exc("criu dump exited with %s" % ret) @@ -1357,7 +1357,7 @@ def dump(self, action, opts=[]): if self.__page_server_p: ret = self.__page_server_p.wait() - grep_errors(os.path.join(self.__ddir(), "page-server.log")) + grep_errors(os.path.join(self.__ddir(), "page-server.log"), err=ret) self.__page_server_p = None if ret: raise test_fail_exc("criu page-server exited with %d" % ret) @@ -2165,7 +2165,7 @@ def print_error(line): return False -def grep_errors(fname): +def grep_errors(fname, err=False): first = True print_next = False before = [] @@ -2186,6 +2186,17 @@ def grep_errors(fname): if print_next: print_next = print_error(line) before = [] + + # If process failed but there are no errors in log, + # let's just print the log tail, probably it would + # be helpful. + if err and first: + print_fname(fname, 'log') + print_sep("grep Error (no)", "-", 60) + first = False + for i in before: + print_next = print_error(i) + if not first: print_sep("ERROR OVER", "-", 60) From 9cc1f051efc6893bdb7f14b05638534e4e7f765b Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Fri, 20 Nov 2020 12:40:20 +0300 Subject: [PATCH 051/204] vim: remove wrong 8-space tabs indent from python files Probably all vim users can setup their desired indent in their vimrc by themselfs. Signed-off-by: Pavel Tikhomirov --- test/crit-recode.py | 2 -- test/inhfd/tty.py | 1 - test/zdtm.py | 1 - 3 files changed, 4 deletions(-) diff --git a/test/crit-recode.py b/test/crit-recode.py index adaf337336..4135681e11 100755 --- a/test/crit-recode.py +++ b/test/crit-recode.py @@ -1,6 +1,4 @@ #!/usr/bin/env python -# vim: noet ts=8 sw=8 sts=8 - import pycriu import sys import os diff --git a/test/inhfd/tty.py b/test/inhfd/tty.py index c11a57117e..984f60c64e 100755 --- a/test/inhfd/tty.py +++ b/test/inhfd/tty.py @@ -1,4 +1,3 @@ -# vim: noet ts=8 sw=8 sts=8 import fcntl import os import pty diff --git a/test/zdtm.py b/test/zdtm.py index a33807050f..9488c6edb9 100755 --- a/test/zdtm.py +++ b/test/zdtm.py @@ -1,5 +1,4 @@ #!/usr/bin/env python -# vim: noet ts=8 sw=8 sts=8 from __future__ import absolute_import, division, print_function, unicode_literals import argparse From 55a8b099ddf7003bf6755ff831b6aeecaabf0d2c Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Sun, 29 Nov 2020 19:08:26 +1100 Subject: [PATCH 052/204] docs: fix simple typo, clietn -> client There is a small typo in test/zdtm/static/socket_aio.c, test/zdtm/static/socket_listen.c, test/zdtm/static/socket_listen4v6.c, test/zdtm/static/socket_listen6.c, test/zdtm/static/socket_udp-corked.c, test/zdtm/static/socket_udp.c, test/zdtm/static/socket_udplite.c. Should read `client` rather than `clietn`. Signed-off-by: Tim Gates --- test/zdtm/static/socket_aio.c | 2 +- test/zdtm/static/socket_listen.c | 2 +- test/zdtm/static/socket_udp-corked.c | 2 +- test/zdtm/static/socket_udp.c | 2 +- test/zdtm/static/socket_udplite.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/zdtm/static/socket_aio.c b/test/zdtm/static/socket_aio.c index b276adb2b8..1dcdfec42c 100644 --- a/test/zdtm/static/socket_aio.c +++ b/test/zdtm/static/socket_aio.c @@ -5,7 +5,7 @@ const char *test_author = "Andrew Vagin "; /* Description: * Create two tcp socket, server send asynchronous request on - * read data and clietn write data after migration + * read data and client write data after migration */ #include diff --git a/test/zdtm/static/socket_listen.c b/test/zdtm/static/socket_listen.c index d0acfd9118..a4d3e66bd7 100644 --- a/test/zdtm/static/socket_listen.c +++ b/test/zdtm/static/socket_listen.c @@ -16,7 +16,7 @@ const char *test_author = "Stanislav Kinsbursky "; /* Description: * Create two tcp socket, server send asynchronous request on - * read data and clietn write data after migration + * read data and client write data after migration */ #include diff --git a/test/zdtm/static/socket_udp-corked.c b/test/zdtm/static/socket_udp-corked.c index 30cfac5ec6..540b9456a0 100644 --- a/test/zdtm/static/socket_udp-corked.c +++ b/test/zdtm/static/socket_udp-corked.c @@ -5,7 +5,7 @@ const char *test_author = "Pavel Emelyanov \n"; /* Description: * Create two tcp socket, server send asynchronous request on - * read data and clietn write data after migration + * read data and client write data after migration */ #include diff --git a/test/zdtm/static/socket_udp.c b/test/zdtm/static/socket_udp.c index 36a954237c..cce29fc96e 100644 --- a/test/zdtm/static/socket_udp.c +++ b/test/zdtm/static/socket_udp.c @@ -5,7 +5,7 @@ const char *test_author = "Pavel Emelyanov \n"; /* Description: * Create two tcp socket, server send asynchronous request on - * read data and clietn write data after migration + * read data and client write data after migration */ #include diff --git a/test/zdtm/static/socket_udplite.c b/test/zdtm/static/socket_udplite.c index 229005a106..763df319bb 100644 --- a/test/zdtm/static/socket_udplite.c +++ b/test/zdtm/static/socket_udplite.c @@ -5,7 +5,7 @@ const char *test_author = "Pavel Emelyanov \n"; /* Description: * Create two tcp socket, server send asynchronous request on - * read data and clietn write data after migration + * read data and client write data after migration */ #include From b27c7e9c861e736ea4db303096d98249efed378d Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Thu, 3 Dec 2020 10:22:18 +0300 Subject: [PATCH 053/204] compel/handle-elf: override unexpected precalculated addresses We've seen addresses in parasite.built-in.o precalculated by linker but in some unexpected manner: readelf -WS criu/pie/parasite.built-in.o Section Headers: [Nr] Name Type Address Off Size ES Flg Lk Inf Al [ 1] .text PROGBITS 0000000000000000 000040 00400a 00 AX 0 0 16 [87] .data PROGBITS 0000000000000000 005000 000068 00 WA 0 0 4096 [88] .rodata PROGBITS 0000000000000080 005080 001016 00 A 0 0 32 (Notes: All other sections does not have SHF_ALLOC or are of size 0, so I skip them. Need to add "-specs=/usr/lib/rpm/redhat/redhat-annobin-cc1" to CFLAGS to reproduce.) Section 88 has address 0x80 in elf file but in our "consequent" addresses precalculation algorithm it should be at 0x5080: addr(.text) == 0x0 addr(.data) == 0x400a + (0x1000 - 0x400a % 0x1000) + 0x68 == 0x5068 addr(.rodata) == 0x5068 + (0x20 - 0x5068 % 0x20) == 0x5080 Probably the linker advises us to move 4096 aligned section to the beginning to save some space, but it's just a guess. So probably we should be ready to "non-consequent" alignments precalculated and just override them. https://github.com/checkpoint-restore/criu/issues/1301 Signed-off-by: Pavel Tikhomirov --- compel/src/lib/handle-elf.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/compel/src/lib/handle-elf.c b/compel/src/lib/handle-elf.c index e505f2c432..2d643ce438 100644 --- a/compel/src/lib/handle-elf.c +++ b/compel/src/lib/handle-elf.c @@ -212,13 +212,11 @@ int __handle_elf(void *mem, size_t size) if (sh->sh_addralign > 0 && k % sh->sh_addralign != 0) { k += sh->sh_addralign - k % sh->sh_addralign; } - if (sh->sh_addr && sh->sh_addr != k) { - pr_err("Unexpected precalculated address of section (section %s addr 0x%lx expected 0x%lx)\n", - &secstrings[sh->sh_name], - (unsigned long) sh->sh_addr, - (unsigned long) k); - goto err; - } + if (sh->sh_addr && sh->sh_addr != k) + pr_info("Overriding unexpected precalculated address of section (section %s addr 0x%lx expected 0x%lx)\n", + &secstrings[sh->sh_name], + (unsigned long) sh->sh_addr, + (unsigned long) k); sh->sh_addr = k; k += sh->sh_size; } From 5db1657abf8877d9f61342163c74fa7f32c0c99a Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Tue, 27 Oct 2020 18:26:35 +0300 Subject: [PATCH 054/204] cr-restore: make CLONE_NEWPID flag in clone_flags more consistent I) Let's make CLONE_NEWPID in rsti(item)->clone_flags always only mean that we need to clone with CLONE_NEWPID to create this task. Only pidns reaper would have this flag because only they can be restored via clone with CLONE_NEWPID flag. If we have non pidns reaper root task but its pidns is different from criu this can be only restored into external pidns. II) Let's remove clone_flags variable from fork_with_pid as it does not actually needed now: clone_flags was introduced to be able to restore into external pidns rsti(item)->clone_flags is determined in prepare_pstree_kobj_ids and before (I) it means 1) parent has different namespace from item or 2) item is root task and criu has different namespace from it. We don't support nested pid namespaces so (1) is always false. And for (2) we have two cases a) pid == INIT_PID - when it is not possible to restore into external pidns b) pid != INIT_PID - when it is only possible to restore into external pidns. For (b) we previousely had CLONE_NEWPID flag in rsti(item)->clone_flags and to workaround it we've added this extra clone_flags variable, but I think it is not needed because we can simply remove CLONE_NEWPID from non-reaper processes initially. Also the code with removing CLONE_NEWPID from clone_flags and adding the same flag to rsti(item)->clone_flags is super strange because I don't see any other place where we later can use rsti(item)->clone_flags. III) Also don't print differen flags in "Forking task with ..." from which we actually use in clone. Signed-off-by: Pavel Tikhomirov --- criu/cr-restore.c | 36 +++++++++++++----------------------- criu/pstree.c | 6 ++++++ 2 files changed, 19 insertions(+), 23 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 8af2e2974a..416f576302 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1363,7 +1363,6 @@ static int set_next_pid(void *arg) static inline int fork_with_pid(struct pstree_item *item) { - unsigned long clone_flags; struct cr_clone_arg ca; struct ns_id *pid_ns = NULL; int ret = -1; @@ -1404,17 +1403,9 @@ static inline int fork_with_pid(struct pstree_item *item) ca.core = NULL; } - ca.item = item; - ca.clone_flags = rsti(item)->clone_flags; - - BUG_ON(ca.clone_flags & CLONE_VM); + if (item->ids) + pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc); - pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags); - - if (ca.item->ids) - pid_ns = lookup_ns_by_id(ca.item->ids->pid_ns_id, &pid_ns_desc); - - clone_flags = ca.clone_flags; if (pid_ns && pid_ns->ext_key) { int fd; @@ -1424,13 +1415,6 @@ static inline int fork_with_pid(struct pstree_item *item) return -1; } - /* - * Restoring into an existing namespace means that CLONE_NEWPID - * needs to be removed during clone() as the process will be - * created in the correct PID namespace thanks to switch_ns_by_fd(). - */ - clone_flags &= ~CLONE_NEWPID; - fd = inherit_fd_lookup_id(pid_ns->ext_key); if (fd < 0) { pr_err("Unable to find an external pidns: %s\n", pid_ns->ext_key); @@ -1450,10 +1434,16 @@ static inline int fork_with_pid(struct pstree_item *item) * process as if using CLONE_NEWPID. */ root_ns_mask |= CLONE_NEWPID; - rsti(item)->clone_flags |= CLONE_NEWPID; } - if (!(clone_flags & CLONE_NEWPID)) { + ca.item = item; + ca.clone_flags = rsti(item)->clone_flags; + + BUG_ON(ca.clone_flags & CLONE_VM); + + pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags); + + if (!(ca.clone_flags & CLONE_NEWPID)) { lock_last_pid(); if (!kdat.has_clone3_set_tid) { @@ -1485,7 +1475,7 @@ static inline int fork_with_pid(struct pstree_item *item) if (kdat.has_clone3_set_tid) { ret = clone3_with_pid_noasan(restore_task_with_children, - &ca, (clone_flags & + &ca, (ca.clone_flags & ~(CLONE_NEWNET | CLONE_NEWCGROUP | CLONE_NEWTIME)), SIGCHLD, pid); } else { @@ -1503,7 +1493,7 @@ static inline int fork_with_pid(struct pstree_item *item) */ close_pid_proc(); ret = clone_noasan(restore_task_with_children, - (clone_flags & + (ca.clone_flags & ~(CLONE_NEWNET | CLONE_NEWCGROUP | CLONE_NEWTIME)) | SIGCHLD, &ca); } @@ -1523,7 +1513,7 @@ static inline int fork_with_pid(struct pstree_item *item) } err_unlock: - if (!(clone_flags & CLONE_NEWPID)) + if (!(ca.clone_flags & CLONE_NEWPID)) unlock_last_pid(); if (ca.core) diff --git a/criu/pstree.c b/criu/pstree.c index f1513dc81a..533f6c0643 100644 --- a/criu/pstree.c +++ b/criu/pstree.c @@ -906,6 +906,12 @@ static int prepare_pstree_kobj_ids(void) */ rsti(item)->clone_flags &= ~CLONE_NEWNS; + /** + * Only child reaper can clone with CLONE_NEWPID + */ + if (vpid(item) != INIT_PID) + rsti(item)->clone_flags &= ~CLONE_NEWPID; + cflags &= CLONE_ALLNS; if (item == root_item) { From c72901dcb2e1e9c56407062c9216066ac6ed331d Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Wed, 28 Oct 2020 11:45:55 +0300 Subject: [PATCH 055/204] namespaces: make root_ns_mask more consistent I) Make root_ns_mask always display namespaces of root task which are different from criu ones. All this play with temporary unsetting it makes this variable hard to understand (more over it is not in shared memory). II) Disable "INIT_PID + pidns is dumped" check for external pidns explicitly. III) On dump we should check that pidns of root task is external, not just any pidns is external (in case in future we would support nested pidns-es it would be wrong). That also allows us to use regular lookup_ns_by_id search. IV) On error when killing tasks we should kill only root task if it is an init of pidns. Previousely we had CLONE_NEWPID set in root_ns_mask for external pidns but root task was not init and we killed only root task on error cleanup. Signed-off-by: Pavel Tikhomirov --- criu/cr-restore.c | 24 +++++++++++++----------- criu/namespaces.c | 34 +++++++++++----------------------- 2 files changed, 24 insertions(+), 34 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 416f576302..4cc87b4820 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1427,13 +1427,6 @@ static inline int fork_with_pid(struct pstree_item *item) pr_err("Unable to enter existing PID namespace\n"); return -1; } - - /* - * If a process without a PID namespace is restored into - * a PID namespace this tells CRIU to still handle the - * process as if using CLONE_NEWPID. - */ - root_ns_mask |= CLONE_NEWPID; } ca.item = item; @@ -2254,9 +2247,18 @@ static int restore_root_task(struct pstree_item *init) "\"--namespace pid\" option.\n"); return -1; } - } else if (root_ns_mask & CLONE_NEWPID) { - pr_err("Can't restore pid namespace without the process init\n"); - return -1; + } else if (root_ns_mask & CLONE_NEWPID) { + struct ns_id *ns; + /* + * Restoring into an existing PID namespace. This disables + * the check to require a PID 1 when restoring a process + * which used to be in a PID namespace. + */ + ns = lookup_ns_by_id(init->ids->pid_ns_id, &pid_ns_desc); + if (!ns || !ns->ext_key) { + pr_err("Can't restore pid namespace without the process init\n"); + return -1; + } } __restore_switch_stage_nw(CR_STATE_ROOT_TASK); @@ -2476,7 +2478,7 @@ static int restore_root_task(struct pstree_item *init) * The processes can be killed only when all of them have been created, * otherwise an external processes can be killed. */ - if (root_ns_mask & CLONE_NEWPID) { + if (vpid(root_item) == INIT_PID) { int status; /* Kill init */ diff --git a/criu/namespaces.c b/criu/namespaces.c index 384c9ca0c0..296e0e3fe8 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -1082,21 +1082,18 @@ int dump_namespaces(struct pstree_item *item, unsigned int ns_flags) pr_info("Dumping %d(%d)'s namespaces\n", ns_pid->ns[0].virt, ns_pid->real); - if ((ns_flags & CLONE_NEWPID) && ns_pid->ns[0].virt != 1) { + if ((ns_flags & CLONE_NEWPID) && ns_pid->ns[0].virt != INIT_PID) { char *val = NULL; - for (ns = ns_ids; ns; ns = ns->next) { - if (ns->nd->cflag == CLONE_NEWPID) { - char id[64]; - snprintf(id, sizeof(id), "pid[%u]", ns->kid); - val = external_lookup_by_key(id); - if (IS_ERR_OR_NULL(val)) { - val = NULL; - continue; - } - if (val) - break; - } + + ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc); + if (ns) { + char id[64]; + snprintf(id, sizeof(id), "pid[%u]", ns->kid); + val = external_lookup_by_key(id); + if (IS_ERR_OR_NULL(val)) + val = NULL; } + if (!val) { pr_err("Can't dump a pid namespace without the process init\n"); return -1; @@ -1801,17 +1798,8 @@ static int read_pid_ns_img(void) pr_err("Can not read pidns object\n"); return -1; } - if (ret > 0) { + if (ret > 0) ns->ext_key = e->ext_key; - /* - * Restoring into an existing PID namespace. This disables - * the check to require a PID 1 when restoring a process - * which used to be in a PID namespace. - * To keep the PID namespace code paths enabled this bit - * will be set after having clone()ed the process. - */ - root_ns_mask &= ~CLONE_NEWPID; - } } return 0; From 660e12843c1da7a28eb1225bfb8d7f5b3d186b09 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Wed, 28 Oct 2020 13:24:36 +0300 Subject: [PATCH 056/204] cr-restore: setup external pidns only for root task All other tasks will inherit, let's remove excess steps. While on it also add some info message about external pidns used. Signed-off-by: Pavel Tikhomirov --- v2: add new external_pidns variable to sinchronize all uses of external pidns case --- criu/cr-restore.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 4cc87b4820..4d98a07900 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -1365,6 +1365,7 @@ static inline int fork_with_pid(struct pstree_item *item) { struct cr_clone_arg ca; struct ns_id *pid_ns = NULL; + bool external_pidns = false; int ret = -1; pid_t pid = vpid(item); @@ -1406,7 +1407,10 @@ static inline int fork_with_pid(struct pstree_item *item) if (item->ids) pid_ns = lookup_ns_by_id(item->ids->pid_ns_id, &pid_ns_desc); - if (pid_ns && pid_ns->ext_key) { + if (!current && pid_ns && pid_ns->ext_key) + external_pidns = true; + + if (external_pidns) { int fd; /* Not possible to restore into an empty PID namespace. */ @@ -1427,6 +1431,8 @@ static inline int fork_with_pid(struct pstree_item *item) pr_err("Unable to enter existing PID namespace\n"); return -1; } + + pr_info("Inheriting external pidns %s for %d\n", pid_ns->ext_key, pid); } ca.item = item; @@ -1440,7 +1446,7 @@ static inline int fork_with_pid(struct pstree_item *item) lock_last_pid(); if (!kdat.has_clone3_set_tid) { - if (pid_ns && pid_ns->ext_key) { + if (external_pidns) { /* * Restoring into another namespace requires a helper * to write to LAST_PID_PATH. Using clone3() this is @@ -1457,7 +1463,7 @@ static inline int fork_with_pid(struct pstree_item *item) } } } else { - if (!(pid_ns && pid_ns->ext_key)) { + if (!external_pidns) { if (pid != INIT_PID) { pr_err("First PID in a PID namespace needs to be %d and not %d\n", pid, INIT_PID); From a9d08735f196e19e0f692e0a3f00f8d3b1f358f1 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Mon, 2 Nov 2020 15:00:58 +0300 Subject: [PATCH 057/204] others/ns_ext: restore a process out of PID namespaces into the host PID namespace It is quiet a common case to move the process from one pidns to another existing pidns with criu (only restriction is pids should not intersect). Let's check it works. v2: - use pipe-s to synchronize processes - run the test in a pid namespace to avoid pid conflicts in the host pid namespace - grep errors in restore.log - add some more comments v3: use 1000 for ns_last_pid so that test works on systems with low pid_max; remove excess ';'s. Co-Developed-by: Andrei Vagin Signed-off-by: Pavel Tikhomirov --- test/others/ns_ext/Makefile | 9 ++++- test/others/ns_ext/__run_pidns.sh | 21 +++++++++++ test/others/ns_ext/_run_pidns.sh | 33 +++++++++++++++++ test/others/ns_ext/run_pidns.sh | 59 +++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 test/others/ns_ext/__run_pidns.sh create mode 100644 test/others/ns_ext/_run_pidns.sh create mode 100755 test/others/ns_ext/run_pidns.sh diff --git a/test/others/ns_ext/Makefile b/test/others/ns_ext/Makefile index f859b89bca..d15224d52c 100644 --- a/test/others/ns_ext/Makefile +++ b/test/others/ns_ext/Makefile @@ -1,7 +1,14 @@ -run: +run: run_pidns run_net run_pid + +run_net: ./run.sh net + +run_pid: ./run.sh pid +run_pidns: + unshare -fp -m --mount-proc --propagation private ./run_pidns.sh + clean: rm -rf images output pidfile pidfile2 pidfile3 .PHONY: clean run diff --git a/test/others/ns_ext/__run_pidns.sh b/test/others/ns_ext/__run_pidns.sh new file mode 100644 index 0000000000..50cdb6b760 --- /dev/null +++ b/test/others/ns_ext/__run_pidns.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +set -e + +status_fd=$1 + +exec 0/dev/null +exec 1>/dev/null + +# Sending our real pid to run_pidns.sh over pipe + +exec {fd}&- +echo $pid >&$status_fd +exec {status_fd}>&- + +while :; do + sleep 10000 +done diff --git a/test/others/ns_ext/_run_pidns.sh b/test/others/ns_ext/_run_pidns.sh new file mode 100644 index 0000000000..b0b266ad6d --- /dev/null +++ b/test/others/ns_ext/_run_pidns.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +set -e + +status_fd=$1 + +# Note that with this block we only guaranty that pid of +# __run_pidns.sh would be somewhere around 1000, not +# exactly 1000. + +mkdir -p pidns_proc +mount -t proc proc pidns_proc +echo 1000 > pidns_proc/sys/kernel/ns_last_pid +umount -l pidns_proc +rmdir pidns_proc + +# Here we create a pipe to wait for __run_pidns.sh to die, +# when it dies the pipe_w is closed and read from pipe_r +# is unblocked. + +exec {pipe}<> <(:) +exec {pipe_r}/proc/self/fd/$pipe +exec {pipe}>&- + +setsid bash __run_pidns.sh $status_fd & +exec {pipe_w}>&- +exec {status_fd}>&- + +# Waiting for __run_pidns.sh to be checkpointed + +cat <&$pipe_r +echo "Temporary pidns init is exiting..." diff --git a/test/others/ns_ext/run_pidns.sh b/test/others/ns_ext/run_pidns.sh new file mode 100755 index 0000000000..b4c7b88a8f --- /dev/null +++ b/test/others/ns_ext/run_pidns.sh @@ -0,0 +1,59 @@ +#!/bin/bash + +set -e + +# This test creates a process in non-host pidns and then dumps it and restores +# it into host pidns. We use pid >100000 in non-host pidns to make sure it does +# not intersect with some host pid on restore but it is potentially racy so +# please run this test only in manualy. + +CRIU=../../../criu/criu + +# This is a status pipe to report the pid of __run_pidns.sh +exec {pipe}<> <(:) +exec {pipe_r}/proc/self/fd/$pipe +exec {pipe}>&- + +unshare -p sh -c "bash _run_pidns.sh $pipe_w &" +exec {pipe_w}>&- + +PID=$(cat <&$pipe_r) +echo PID: $PID + +PIDNS=$(readlink /proc/$PID/ns/pid | sed 's/://') +echo PIDNS: $PIDNS + +BEFORE=$(grep NSpid /proc/$PID/status) +echo "before c/r: $BEFORE" + +rm -rf images_pidns || : +mkdir -p images_pidns + +echo "$CRIU dump -v4 -o dump.log -t $PID -D images_pidns --external $PIDNS:exti" +$CRIU dump -v4 -o dump.log -t $PID -D images_pidns --external $PIDNS:exti +RESULT=$? +cat images_pidns/dump.log | grep -B 5 Error || echo ok +[ "$RESULT" != "0" ] && { + echo "CRIU dump failed" + echo FAIL + exit 1 +} + +exec {pidns_fd}< /proc/self/ns/pid + +echo "$CRIU restore -v4 -o restore.log -D images_pidns --restore-detached --inherit-fd fd[$pidns_fd]:exti" +$CRIU restore -v4 -o restore.log -D images_pidns --restore-detached --inherit-fd fd[$pidns_fd]:exti --pidfile test.pidfile +RESULT=$? +cat images_pidns/restore.log | grep -B 5 Error || echo ok +[ "$RESULT" != "0" ] && { + echo "CRIU restore failed" + echo FAIL + exit 1 +} + +PID=$(cat images_pidns/test.pidfile) +AFTER=$(grep NSpid /proc/$PID/status) +echo "after c/r: $AFTER" +echo PASS +exit 0 From e0da8b895ede46e197e9813dc87b55f4b1a7e93c Mon Sep 17 00:00:00 2001 From: anatasluo Date: Thu, 3 Dec 2020 10:53:43 +0000 Subject: [PATCH 058/204] x86/asm: fix compile error in bitops.h Build on Ubuntu 18.04 amd64 with command "make DEBUG=1" produces the following error: include/common/asm/bitops.h: Assembler messages: include/common/asm/bitops.h:71: Error: incorrect register `%edx' used with `q' suffix Signed-off-by: anatasluo --- include/common/arch/x86/asm/asm.h | 28 ++++++++++++++++++++++++++++ include/common/arch/x86/asm/bitops.h | 27 ++++++++++----------------- 2 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 include/common/arch/x86/asm/asm.h diff --git a/include/common/arch/x86/asm/asm.h b/include/common/arch/x86/asm/asm.h new file mode 100644 index 0000000000..af324c6e2a --- /dev/null +++ b/include/common/arch/x86/asm/asm.h @@ -0,0 +1,28 @@ +#ifndef __CR_ASM_H__ +#define __CR_ASM_H__ + +#ifdef __GCC_ASM_FLAG_OUTPUTS__ +# define CC_SET(c) "\n\t/* output condition code " #c "*/\n" +# define CC_OUT(c) "=@cc" #c +#else +# define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n" +# define CC_OUT(c) [_cc_ ## c] "=qm" +#endif + +#ifdef __ASSEMBLY__ +# define __ASM_FORM(x) x +#else +# define __ASM_FORM(x) " " #x " " +#endif + +#ifndef __x86_64__ +/* 32 bit */ +# define __ASM_SEL(a,b) __ASM_FORM(a) +#else +/* 64 bit */ +# define __ASM_SEL(a,b) __ASM_FORM(b) +#endif + +#define __ASM_SIZE(inst, ...) __ASM_SEL(inst##l##__VA_ARGS__, inst##q##__VA_ARGS__) + +#endif /* __CR_ASM_H__ */ diff --git a/include/common/arch/x86/asm/bitops.h b/include/common/arch/x86/asm/bitops.h index c69e0ed029..9c7aeb5d73 100644 --- a/include/common/arch/x86/asm/bitops.h +++ b/include/common/arch/x86/asm/bitops.h @@ -3,16 +3,9 @@ #include #include "common/arch/x86/asm/cmpxchg.h" +#include "common/arch/x86/asm/asm.h" #include "common/asm/bitsperlong.h" -#ifdef __GCC_ASM_FLAG_OUTPUTS__ -# define CC_SET(c) "\n\t/* output condition code " #c "*/\n" -# define CC_OUT(c) "=@cc" #c -#else -# define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n" -# define CC_OUT(c) [_cc_ ## c] "=qm" -#endif - #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_LONG) @@ -29,21 +22,21 @@ #define ADDR BITOP_ADDR(addr) -static inline void set_bit(int nr, volatile unsigned long *addr) +static inline void set_bit(long nr, volatile unsigned long *addr) { - asm volatile("btsl %1,%0" : ADDR : "Ir" (nr) : "memory"); + asm volatile(__ASM_SIZE(bts) " %1,%0" : ADDR : "Ir" (nr) : "memory"); } -static inline void change_bit(int nr, volatile unsigned long *addr) +static inline void change_bit(long nr, volatile unsigned long *addr) { - asm volatile("btcl %1,%0" : ADDR : "Ir" (nr)); + asm volatile(__ASM_SIZE(btc) " %1,%0" : ADDR : "Ir" (nr)); } static inline bool test_bit(long nr, volatile const unsigned long *addr) { bool oldbit; - asm volatile("btq %2,%1" + asm volatile(__ASM_SIZE(bt) " %2,%1" CC_SET(c) : CC_OUT(c) (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr) : "memory"); @@ -51,9 +44,9 @@ static inline bool test_bit(long nr, volatile const unsigned long *addr) return oldbit; } -static inline void clear_bit(int nr, volatile unsigned long *addr) +static inline void clear_bit(long nr, volatile unsigned long *addr) { - asm volatile("btrl %1,%0" : ADDR : "Ir" (nr)); + asm volatile(__ASM_SIZE(btr) " %1,%0" : ADDR : "Ir" (nr)); } /** @@ -64,11 +57,11 @@ static inline void clear_bit(int nr, volatile unsigned long *addr) * This operation is atomic and cannot be reordered. * It also implies a memory barrier. */ -static inline bool test_and_set_bit(int nr, volatile unsigned long *addr) +static inline bool test_and_set_bit(long nr, volatile unsigned long *addr) { bool oldbit; - asm("btsq %2,%1" + asm(__ASM_SIZE(bts) " %2,%1" CC_SET(c) : CC_OUT(c) (oldbit) : "m" (*(unsigned long *)addr), "Ir" (nr) : "memory"); From bde4e8565da3b509e43432c6d60085a875eee74e Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 14 Dec 2020 10:00:04 +0000 Subject: [PATCH 059/204] scripts/Docerfile.centos8: Use 'powertools' repo name See https://bugs.centos.org/view.php?id=17920 Signed-off-by: Dmitry Safonov --- scripts/build/Dockerfile.centos8 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build/Dockerfile.centos8 b/scripts/build/Dockerfile.centos8 index 0b658d5fa3..e3aabbe599 100644 --- a/scripts/build/Dockerfile.centos8 +++ b/scripts/build/Dockerfile.centos8 @@ -4,7 +4,7 @@ ARG CC=gcc ARG ENV1=FOOBAR RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm dnf-plugins-core -RUN yum config-manager --set-enabled PowerTools +RUN yum config-manager --set-enabled powertools RUN yum install -y --allowerasing \ asciidoc \ ccache \ From e403226ce6f74a4448015568cc15d6da6ea372a1 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Mon, 14 Dec 2020 10:11:49 +0000 Subject: [PATCH 060/204] .gitignore: Remove qemu-user-static Not a thing since commit fe668075ad2a ("travis: switch pcp64le and s390x to real hardware"). Signed-off-by: Dmitry Safonov --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 23cd703be2..3b3da545cc 100644 --- a/.gitignore +++ b/.gitignore @@ -37,7 +37,6 @@ criu/pie/parasite-blob.h criu/protobuf-desc-gen.h lib/build/ lib/c/criu.pc -scripts/build/qemu-user-static/* lib/.crit-setup.files compel/include/asm include/common/asm From ac9843b089140f9a6391cc2e03b80f49a116fc05 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Fri, 18 Dec 2020 12:03:17 +0300 Subject: [PATCH 061/204] CONTRIBUTING.md: add component prefix to the subject example If one will do "git log --oneline", it is quite easy to see that we don't begin subject lines with a capital letter. We start subjects with component prefixes where components (mostly) are lowercase. So let's fix it in contribution guide not to mislead newcomers. Signed-off-by: Pavel Tikhomirov --- CONTRIBUTING.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5d803d0208..96972296e0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -126,6 +126,19 @@ If your change address an issue listed in GitHub, please use `Fixes:` tag with t The `Fixes:` tags should be put at the end of the detailed description. +Please add a prefix to your commit subject line describing the part of the +project your change is related to. This can be either the name of the file or +directory you changed, or just a general word. If your patch is touching +multiple components you may separate prefixes with "/"-es. Here are some good +examples of subject lines from git log: + +``` +criu-ns: Convert to python3 style print() syntax +compel: Calculate sh_addr if not provided by linker +style: Enforce kernel style -Wstrict-prototypes +rpc/libcriu: Add lsm-profile option +``` + You may refer to [How to Write a Git Commit Message](https://chris.beams.io/posts/git-commit/) article for recommendations for good commit message. @@ -203,7 +216,7 @@ commit message. To append such line to a commit you already made, use ``` From: Random J Developer - Subject: [PATCH] Short patch description + Subject: [PATCH] component: Short patch description Long patch description (could be skipped if patch is trivial enough) From 52bbac5a9a4f1f75546bee1c753d5e8b29c65af8 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 16 Dec 2020 18:58:23 +0000 Subject: [PATCH 062/204] ci: add Circle CI definition Circle CI provides bare metal test systems which are a very good environment for the CRIU test cases. This adds two CI runs on Circle CI. On Circle CI it is necessary to tell clang to use '-Wl,-z,now', because gcc has it hard-coded in Ubuntu and clang does not. Signed-off-by: Adrian Reber --- .circleci/config.yml | 27 +++++++++++++++++++++++++++ .travis.yml | 6 ------ scripts/ci/run-ci-tests.sh | 8 +++++++- 3 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 .circleci/config.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 0000000000..47f7ad9b18 --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,27 @@ +version: 2.1 +jobs: + test-local-gcc: + machine: + image: ubuntu-2004:202010-01 + working_directory: ~/criu + steps: + - checkout + - run: + name: "Test local with GCC" + command: sudo -E make -C scripts/ci local + test-local-clang: + machine: + image: ubuntu-2004:202010-01 + working_directory: ~/criu + steps: + - checkout + - run: + name: "Test local with CLANG" + command: sudo -E make -C scripts/ci local CLANG=1 + +workflows: + version: 2 + builds: + jobs: + - test-local-gcc + - test-local-clang diff --git a/.travis.yml b/.travis.yml index a82ed910ca..a94eb5edb8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,17 +5,11 @@ cache: ccache services: - docker env: - - TR_ARCH=local - - TR_ARCH=local CLANG=1 - TR_ARCH=local COMPAT_TEST=y - TR_ARCH=local CLANG=1 COMPAT_TEST=y - TR_ARCH=vagrant-fedora-no-vdso jobs: include: - - os: linux - arch: amd64 - env: TR_ARCH=local - dist: focal - os: linux arch: ppc64le env: TR_ARCH=local diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 648d5886c3..42062aee9e 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -97,6 +97,12 @@ test_stream() { ci_prep +if [ "$CLANG" = "1" ]; then + # Needed for clang on Circle CI + LDFLAGS="$LDFLAGS -Wl,-z,now" + export LDFLAGS +fi + export GCOV $CC --version time make CC="$CC" -j4 @@ -204,7 +210,7 @@ if [ -z "$SKIP_EXT_DEV_TEST" ]; then fi #make -C test/others/exec/ run make -C test/others/make/ run CC="$CC" -if [ -n "$TRAVIS" ]; then +if [ -n "$TRAVIS" ] || [ -n "$CIRCLECI" ]; then # GitHub Actions does not provide a real TTY and CRIU will fail with: # Error (criu/tty.c:1014): tty: Don't have tty to inherit session from, aborting make -C test/others/shell-job/ run From 944bd0b6ea91c8025ed43c32ded8cf337f0243ed Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sun, 20 Dec 2020 17:08:18 +0000 Subject: [PATCH 063/204] ci: give an overview of the current CI environment As CRIU is using multiple different CI systems this adds a printout to each CI run about the CI environment for easier debugging of possible errors. Also use V=1 to build CRIU and the tests to easily see which compiler and which options are used. Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 42062aee9e..29711d3c3b 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -95,6 +95,36 @@ test_stream() { ./test/zdtm.py run --stream -p 2 --keep-going -T "$STREAM_TEST_PATTERN" $ZDTM_OPTS } +print_header() { + echo "############### $1 ###############" +} + +print_env() { + # As this script can run on multiple different CI systems + # the following lines should give some context to the + # evnvironment of this CI run. + print_header "Environment variables" + printenv + print_header "uname -a" + uname -a || : + print_header "Mounted file systems" + mount || : + print_header "Kernel command line" + cat /proc/cmdline || : + print_header "Distribution information" + [ -e /etc/lsb-release ] && cat /etc/lsb-release + [ -e /etc/redhat-release ] && cat /etc/redhat-release + [ -e /etc/alpine-release ] && cat /etc/alpine-release + print_header "ulimit -a" + ulimit -a + print_header "Available memory" + free -h + print_header "Available CPUs" + lscpu || : +} + +print_env + ci_prep if [ "$CLANG" = "1" ]; then @@ -103,9 +133,9 @@ if [ "$CLANG" = "1" ]; then export LDFLAGS fi -export GCOV +export GCOV CC $CC --version -time make CC="$CC" -j4 +time make CC="$CC" -j4 V=1 ./criu/criu -v4 cpuinfo dump || : ./criu/criu -v4 cpuinfo check || : @@ -148,7 +178,7 @@ if [ "${COMPAT_TEST}x" = "yx" ] ; then mv "$REFUGE"/* /usr/lib/x86_64-linux-gnu/ fi -time make CC="$CC" -j4 -C test/zdtm +time make CC="$CC" -j4 -C test/zdtm V=1 [ -f "$CCACHE_LOGFILE" ] && cat "$CCACHE_LOGFILE" From cf8c88df68fdc3c98e9e69ebdd636f1ca1cb77c5 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 17 Dec 2020 13:47:36 +0000 Subject: [PATCH 064/204] ci: move alpine based tests to github actions Signed-off-by: Adrian Reber --- .github/workflows/alpine-test.yml | 15 +++++++++++++++ .travis.yml | 8 -------- 2 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/alpine-test.yml diff --git a/.github/workflows/alpine-test.yml b/.github/workflows/alpine-test.yml new file mode 100644 index 0000000000..6fc546ff54 --- /dev/null +++ b/.github/workflows/alpine-test.yml @@ -0,0 +1,15 @@ +name: Alpine Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + target: [GCC=1, CLANG=1] + + steps: + - uses: actions/checkout@v2 + - name: Run Alpine ${{ matrix.target }} Test + run: sudo -E make -C scripts/ci alpine ${{ matrix.target }} diff --git a/.travis.yml b/.travis.yml index a94eb5edb8..60516df3a5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,14 +62,6 @@ jobs: # On xenial it should be possible to test overlayfs; # broken on the latest bionic kernel dist: xenial - - os: linux - arch: amd64 - env: TR_ARCH=alpine CLANG=1 - dist: bionic - - os: linux - arch: amd64 - env: TR_ARCH=alpine - dist: bionic - os: linux arch: amd64 env: TR_ARCH=fedora-asan From 72fc2e8e403d900e1e60e1b7b367416aca4c1662 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Tue, 10 Nov 2020 15:37:00 +0300 Subject: [PATCH 065/204] namespaces: don't set rst on error in switch_ns_by_fd This is just a small cleanup, no behaviour change. Signed-off-by: Pavel Tikhomirov --- criu/namespaces.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/criu/namespaces.c b/criu/namespaces.c index 296e0e3fe8..c8baf42fc9 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -247,11 +247,11 @@ int switch_ns(int pid, struct ns_desc *nd, int *rst) int switch_ns_by_fd(int nsfd, struct ns_desc *nd, int *rst) { - int ret = -1; + int ret = -1, old_ns = -1; if (rst) { - *rst = open_proc(PROC_SELF, "ns/%s", nd->str); - if (*rst < 0) + old_ns = open_proc(PROC_SELF, "ns/%s", nd->str); + if (old_ns < 0) goto err_ns; } @@ -261,11 +261,12 @@ int switch_ns_by_fd(int nsfd, struct ns_desc *nd, int *rst) goto err_set; } + if (rst) + *rst = old_ns; return 0; err_set: - if (rst) - close(*rst); + close_safe(&old_ns); err_ns: return -1; } From 5351b6efe8d4adeaaaaef47f581392547870d02a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sat, 26 Dec 2020 19:29:58 +0000 Subject: [PATCH 066/204] ci: Alpine's busybox based free does not understand -h Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 29711d3c3b..9b07fd9668 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -118,7 +118,12 @@ print_env() { print_header "ulimit -a" ulimit -a print_header "Available memory" - free -h + if [ -e /etc/alpine-release ]; then + # Alpine's busybox based free does not understand -h + free + else + free -h + fi print_header "Available CPUs" lscpu || : } From cb9c85fb6cbb2b3e711dfdc5e4d26a062e0c2e6a Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Mon, 28 Dec 2020 20:51:27 +0300 Subject: [PATCH 067/204] test/zdtm_ct: Run zdtm.py in the host time namespace Before the 5.11 kernel, there is a known issue. start_time in /proc/pid/stat is printed in the host time namespace, but /proc/uptime is shown in a current namespace, but criu compares them to detect when a new task has reused one of old pids. Fixes: #1266 Signed-off-by: Andrei Vagin --- test/zdtm_ct.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/zdtm_ct.c b/test/zdtm_ct.c index 5495d61eb7..d9823da3fc 100644 --- a/test/zdtm_ct.c +++ b/test/zdtm_ct.c @@ -9,6 +9,7 @@ #include #include #include +#include #ifndef CLONE_NEWTIME #define CLONE_NEWTIME 0x00000080 /* New time namespace */ @@ -42,7 +43,28 @@ static inline int _settime(clockid_t clk_id, time_t offset) static int create_timens() { - int fd; + struct utsname buf; + unsigned major, minor; + int fd, ret; + + /* + * Before the 5.11 kernel, there is a known issue. + * start_time in /proc/pid/stat is printed in the host time + * namespace, but /proc/uptime is shown in the current time + * namespace, so criu can't compare them to detect tasks that + * reuse old pids. + */ + ret = uname(&buf); + if (ret) + return -1; + + if (sscanf(buf.release, "%u.%u", &major, &minor) != 2) + return -1; + + if (major == 5 && minor < 11) { + fprintf(stderr, "timens isn't supported on %s\n", buf.release); + return 0; + } if (unshare(CLONE_NEWTIME)) { if (errno == EINVAL) { From 43023fe75a6912da48da05b939bff491f14ee854 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Fri, 1 Jan 2021 14:20:09 +0300 Subject: [PATCH 068/204] zdtm: look up iptables in /sbin and /usr/sbin On Ubuntu 20.04, iptables is in /usr/sbin/. Reported-by: Mr Jenkins Signed-off-by: Andrei Vagin --- test/zdtm/static/netns-nf.desc | 2 +- test/zdtm/static/socket-tcp-closed-last-ack.desc | 2 +- test/zdtm/static/socket-tcp-reseted.desc | 2 +- test/zdtm/static/socket-tcp-syn-sent.desc | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/zdtm/static/netns-nf.desc b/test/zdtm/static/netns-nf.desc index 8fd3770bd4..67c294888c 100644 --- a/test/zdtm/static/netns-nf.desc +++ b/test/zdtm/static/netns-nf.desc @@ -1,5 +1,5 @@ { 'deps': [ '/bin/sh', - '/sbin/iptables', + '/sbin/iptables|/usr/sbin/iptables', '/usr/lib64/xtables/libxt_standard.so|/usr/lib/iptables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', '/usr/bin/diff'], 'flags': 'suid', diff --git a/test/zdtm/static/socket-tcp-closed-last-ack.desc b/test/zdtm/static/socket-tcp-closed-last-ack.desc index 43afd920eb..8a83de6fdc 100644 --- a/test/zdtm/static/socket-tcp-closed-last-ack.desc +++ b/test/zdtm/static/socket-tcp-closed-last-ack.desc @@ -1,5 +1,5 @@ { 'deps': [ '/bin/sh', - '/sbin/iptables', + '/sbin/iptables|/usr/sbin/iptables', '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_tcp.so', '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', ], diff --git a/test/zdtm/static/socket-tcp-reseted.desc b/test/zdtm/static/socket-tcp-reseted.desc index 744ed88c96..a5c1a209de 100644 --- a/test/zdtm/static/socket-tcp-reseted.desc +++ b/test/zdtm/static/socket-tcp-reseted.desc @@ -1,5 +1,5 @@ { 'deps': [ '/bin/sh', - '/sbin/iptables', + '/sbin/iptables|/usr/sbin/iptables', '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_tcp.so', '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', '/usr/lib64/xtables/libipt_REJECT.so|/lib/xtables/libipt_REJECT.so|/usr/lib/powerpc64le-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/x86_64-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/xtables/libipt_REJECT.so|/usr/lib/s390x-linux-gnu/xtables/libipt_REJECT.so|/usr/lib/aarch64-linux-gnu/xtables/libipt_REJECT.so', diff --git a/test/zdtm/static/socket-tcp-syn-sent.desc b/test/zdtm/static/socket-tcp-syn-sent.desc index a276736812..d59e59717d 100644 --- a/test/zdtm/static/socket-tcp-syn-sent.desc +++ b/test/zdtm/static/socket-tcp-syn-sent.desc @@ -1,5 +1,5 @@ { 'deps': [ '/bin/sh', - '/sbin/iptables', + '/sbin/iptables|/usr/sbin/iptables', '/usr/lib64/xtables/libxt_tcp.so|/lib/xtables/libxt_tcp.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_tcp.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_tcp.so|/usr/lib/xtables/libxt_tcp.so|/usr/lib/s390x-linux-gnu/xtables/libxt_tcp.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_tcp.so', '/usr/lib64/xtables/libxt_standard.so|/lib/xtables/libxt_standard.so|/usr/lib/powerpc64le-linux-gnu/xtables/libxt_standard.so|/usr/lib/x86_64-linux-gnu/xtables/libxt_standard.so|/usr/lib/xtables/libxt_standard.so|/usr/lib/s390x-linux-gnu/xtables/libxt_standard.so|/usr/lib/aarch64-linux-gnu/xtables/libxt_standard.so', ], From b4be97de96b32c875b5b49876d6d2de1b2d19502 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 31 Dec 2020 09:02:30 +0000 Subject: [PATCH 069/204] github: auto-close stale issues and pull requests This is a copy of stale.yml from the Podman repository to automatically close tickets after 365 days. After 30 days tickets and issues are marked as stale and after 365 tickets and issues are finally closed. Signed-off-by: Adrian Reber --- .github/workflows/stale.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/stale.yml diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml new file mode 100644 index 0000000000..29676b9118 --- /dev/null +++ b/.github/workflows/stale.yml @@ -0,0 +1,27 @@ +name: Mark stale issues and pull requests + +# Please refer to https://github.com/actions/stale/blob/master/action.yml +# to see all config knobs of the stale action. + +on: + schedule: + - cron: "0 0 * * *" + +jobs: + stale: + + runs-on: ubuntu-latest + + steps: + - uses: actions/stale@v1 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + stale-issue-message: 'A friendly reminder that this issue had no activity for 30 days.' + stale-pr-message: 'A friendly reminder that this PR had no activity for 30 days.' + stale-issue-label: 'stale-issue' + stale-pr-label: 'stale-pr' + days-before-stale: 30 + days-before-close: 365 + remove-stale-when-updated: true + exempt-pr-labels: 'no-auto-close' + exempt-issue-labels: 'no-auto-close' From f5a408cdd3cfc584a7da744fa21df5c476cbbb0c Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Fri, 1 Jan 2021 01:21:44 +0300 Subject: [PATCH 070/204] dump/ppc64,arm,mips: sanitize the ERESTART_RESTARTBLOCK -> EINTR transition 1. The -ERESTART_RESTARTBLOCK case in get_task_regs() depends on kernel internals too much, and for no reason. We shouldn't rely on fact that a) we are going to do sigreturn() and b) restore_sigcontext() always sets restart_block->fn = do_no_restart_syscall which returns -EINTR. Just change this code to enforce -EINTR after restore, this is what we actually want until we teach criu to handle ERESTART_RESTARTBLOCK. 2. Add pr_warn() to make the potential bug-reports more understandable, a sane application should handle -EINTR correctly but this is not always the case. Fixes: #1325 Report-by: Mr Travis Inspired-by: dd71cca58ada ("dump/x86: sanitize the ERESTART_RESTARTBLOCK -> EINTR transition") Signed-off-by: Andrei Vagin --- compel/arch/arm/src/lib/infect.c | 6 ++++-- compel/arch/mips/src/lib/infect.c | 7 ++++--- compel/arch/ppc64/src/lib/infect.c | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/compel/arch/arm/src/lib/infect.c b/compel/arch/arm/src/lib/infect.c index 0053bef581..75b985b74b 100644 --- a/compel/arch/arm/src/lib/infect.c +++ b/compel/arch/arm/src/lib/infect.c @@ -4,6 +4,8 @@ #include #include #include +#include + #include "common/page.h" #include "uapi/compel/asm/infect-types.h" #include "log.h" @@ -91,8 +93,8 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, regs->ARM_pc -= 4; break; case -ERESTART_RESTARTBLOCK: - regs->ARM_r0 = __NR_restart_syscall; - regs->ARM_pc -= 4; + pr_warn("Will restore %d with interrupted system call\n", pid); + regs->ARM_r0 = -EINTR; break; } } diff --git a/compel/arch/mips/src/lib/infect.c b/compel/arch/mips/src/lib/infect.c index 521528f765..35e947cc0e 100755 --- a/compel/arch/mips/src/lib/infect.c +++ b/compel/arch/mips/src/lib/infect.c @@ -2,6 +2,8 @@ #include #include #include +#include + #include #include #include "errno.h" @@ -142,9 +144,8 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, regs->cp0_epc -= 4; break; case ERESTART_RESTARTBLOCK: - regs->regs[2] = __NR_restart_syscall; - regs->regs[7] = regs->regs[26]; - regs->cp0_epc -= 4; + pr_warn("Will restore %d with interrupted system call\n", pid); + regs->regs[2] = -EINTR; break; } regs->regs[0] = 0; diff --git a/compel/arch/ppc64/src/lib/infect.c b/compel/arch/ppc64/src/lib/infect.c index 637acd46d4..b2c725f62f 100644 --- a/compel/arch/ppc64/src/lib/infect.c +++ b/compel/arch/ppc64/src/lib/infect.c @@ -330,8 +330,8 @@ static int __get_task_regs(pid_t pid, user_regs_struct_t *regs, regs->nip -= 4; break; case ERESTART_RESTARTBLOCK: - regs->gpr[0] = __NR_restart_syscall; - regs->nip -= 4; + pr_warn("Will restore %d with interrupted system call\n", pid); + regs->gpr[3] = EINTR; break; } } From 61db62a8765d06191a461185a7c897dc5d0999e2 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 11 Jan 2021 00:00:02 +0000 Subject: [PATCH 071/204] compel/test: Resolve missing includes Resolves #1333 Signed-off-by: Radostin Stoyanov --- compel/include/uapi/infect-rpc.h | 2 ++ compel/test/fdspy/parasite.c | 4 ++-- compel/test/fdspy/spy.c | 4 ++++ compel/test/infect/spy.c | 3 +++ compel/test/rsys/spy.c | 3 +++ 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/compel/include/uapi/infect-rpc.h b/compel/include/uapi/infect-rpc.h index 180dedf1f6..5fcdb56ff8 100644 --- a/compel/include/uapi/infect-rpc.h +++ b/compel/include/uapi/infect-rpc.h @@ -5,6 +5,8 @@ #include #include +#include + struct parasite_ctl; extern int __must_check compel_rpc_sync(unsigned int cmd, struct parasite_ctl *ctl); extern int __must_check compel_rpc_call(unsigned int cmd, struct parasite_ctl *ctl); diff --git a/compel/test/fdspy/parasite.c b/compel/test/fdspy/parasite.c index c14064b362..7933d29ae2 100644 --- a/compel/test/fdspy/parasite.c +++ b/compel/test/fdspy/parasite.c @@ -1,7 +1,7 @@ #include -#include #include +#include /* * Stubs for std compel plugin. @@ -15,6 +15,6 @@ void parasite_cleanup(void) { } int parasite_daemon_cmd(int cmd, void *args) { if (cmd == PARASITE_CMD_GETFD) - fds_send_fd(2); + return (fds_send_fd(2) < 0); return 0; } diff --git a/compel/test/fdspy/spy.c b/compel/test/fdspy/spy.c index 1a373b6bb0..c6558f0794 100644 --- a/compel/test/fdspy/spy.c +++ b/compel/test/fdspy/spy.c @@ -5,6 +5,10 @@ #include #include +#include +#include +#include + #include "parasite.h" #define PARASITE_CMD_GETFD PARASITE_USER_CMDS diff --git a/compel/test/infect/spy.c b/compel/test/infect/spy.c index b5f8b25593..8be6925c58 100644 --- a/compel/test/infect/spy.c +++ b/compel/test/infect/spy.c @@ -3,6 +3,9 @@ #include #include +#include +#include + #include "parasite.h" #define PARASITE_CMD_INC PARASITE_USER_CMDS diff --git a/compel/test/rsys/spy.c b/compel/test/rsys/spy.c index 98654efcf3..6ccb2a5021 100644 --- a/compel/test/rsys/spy.c +++ b/compel/test/rsys/spy.c @@ -4,6 +4,9 @@ #include #include +#include +#include + static void print_vmsg(unsigned int lvl, const char *fmt, va_list parms) { printf("\tLC%u: ", lvl); From 988b402307045670f8ebaa6923d7b3d660663c76 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 11 Jan 2021 22:41:54 +0000 Subject: [PATCH 072/204] compel/test: Add main makefile These changes enable running all compel tests with a single command from the root path of the repository: # sudo make -C compel/test Signed-off-by: Radostin Stoyanov --- compel/test/Makefile | 17 +++++++++++++++++ compel/test/fdspy/Makefile | 4 ++++ compel/test/infect/Makefile | 4 ++++ compel/test/rsys/Makefile | 4 ++++ 4 files changed, 29 insertions(+) create mode 100644 compel/test/Makefile diff --git a/compel/test/Makefile b/compel/test/Makefile new file mode 100644 index 0000000000..63fb76f80d --- /dev/null +++ b/compel/test/Makefile @@ -0,0 +1,17 @@ +all: fdspy infect rsys + +fdspy: + $(Q) $(MAKE) -C fdspy + $(Q) $(MAKE) -C fdspy run +.PHONY: fdspy + +infect: + $(Q) $(MAKE) -C infect + $(Q) $(MAKE) -C infect run +.PHONY: infect + + +rsys: + $(Q) $(MAKE) -C rsys + $(Q) $(MAKE) -C rsys run +.PHONY: rsys diff --git a/compel/test/fdspy/Makefile b/compel/test/fdspy/Makefile index 027c373fe8..82d9fdc0b2 100644 --- a/compel/test/fdspy/Makefile +++ b/compel/test/fdspy/Makefile @@ -5,6 +5,10 @@ COMPEL := ../../../compel/compel-host all: victim spy +run: + ./spy +.PHONY: run + clean: rm -f victim rm -f spy diff --git a/compel/test/infect/Makefile b/compel/test/infect/Makefile index 4dedf33c95..bacfad9624 100644 --- a/compel/test/infect/Makefile +++ b/compel/test/infect/Makefile @@ -5,6 +5,10 @@ COMPEL := ../../../compel/compel-host all: victim spy +run: + ./spy +.PHONY: run + clean: rm -f victim rm -f spy diff --git a/compel/test/rsys/Makefile b/compel/test/rsys/Makefile index 3babda18f2..53400498e4 100644 --- a/compel/test/rsys/Makefile +++ b/compel/test/rsys/Makefile @@ -5,6 +5,10 @@ COMPEL := ../../../compel/compel-host all: victim spy +run: + ./spy +.PHONY: run + clean: rm -f victim rm -f spy From 1b3274a9094c6ede659df897c770c451a3201d38 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 11 Jan 2021 22:59:06 +0000 Subject: [PATCH 073/204] ci: Enable compel testing Signed-off-by: Radostin Stoyanov --- scripts/ci/run-ci-tests.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 9b07fd9668..1a51d6aeb2 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -279,3 +279,6 @@ make -C test/others/libcriu run # external namespace testing make -C test/others/ns_ext run + +# compel testing +make -C compel/test From cf0337c808a85e795e826db74b16e518467cead8 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 11 Jan 2021 23:38:43 +0000 Subject: [PATCH 074/204] compel: Fix missing loff_t in Alpine musl defines 'loff_t' in fcntl.h as 'off_t'. This patch resolves the following error when running the compel tests on Alpine Linux: gcc -O2 -g -Wall -Werror -c -Wstrict-prototypes -fno-stack-protector -nostdlib -fomit-frame-pointer -ffreestanding -fpie -I ../../../compel/include/uapi -o parasite.o parasite.c In file included from ../../../compel/include/uapi/compel/plugins/std/syscall.h:8, from ../../../compel/include/uapi/compel/plugins/std.h:5, from parasite.c:3: ../../../compel/include/uapi/compel/plugins/std/syscall-64.h:19:66: error: unknown type name 'loff_t'; did you mean 'off_t'? 19 | extern long sys_pread (unsigned int fd, char *buf, size_t count, loff_t pos) ; | ^~~~~~ | off_t ../../../compel/include/uapi/compel/plugins/std/syscall-64.h:96:46: error: unknown type name 'loff_t'; did you mean 'off_t'? 96 | extern long sys_fallocate (int fd, int mode, loff_t offset, loff_t len) ; | ^~~~~~ | off_t ../../../compel/include/uapi/compel/plugins/std/syscall-64.h:96:61: error: unknown type name 'loff_t'; did you mean 'off_t'? 96 | extern long sys_fallocate (int fd, int mode, loff_t offset, loff_t len) ; | ^~~~~~ | off_t make[1]: *** [Makefile:32: parasite.o] Error 1 Signed-off-by: Radostin Stoyanov --- compel/arch/x86/plugins/std/syscalls/Makefile.syscalls | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compel/arch/x86/plugins/std/syscalls/Makefile.syscalls b/compel/arch/x86/plugins/std/syscalls/Makefile.syscalls index 4ba4b56c84..62c25f3e03 100644 --- a/compel/arch/x86/plugins/std/syscalls/Makefile.syscalls +++ b/compel/arch/x86/plugins/std/syscalls/Makefile.syscalls @@ -39,6 +39,10 @@ $(sys-proto): $(sys-def) $(sys-proto-types) $(Q) echo "/* Autogenerated, don't edit */" > $$@ $(Q) echo "#ifndef ASM_SYSCALL_PROTO_H_$(1)__" >> $$@ $(Q) echo "#define ASM_SYSCALL_PROTO_H_$(1)__" >> $$@ + $(Q) echo "/* musl defines loff_t as off_t */" >> $$@ + $(Q) echo '#ifndef loff_t' >> $$@ + $(Q) echo '#define loff_t off_t' >> $$@ + $(Q) echo '#endif' >> $$@ $(Q) echo '#include ' >> $$@ $(Q) echo '#include ' >> $$@ ifeq ($(1),32) @@ -71,6 +75,10 @@ $(sys-codes-generic): $(PLUGIN_ARCH_DIR)/std/syscalls/syscall_32.tbl $(sys-proto $(Q) echo "/* Autogenerated, don't edit */" > $@ $(Q) echo "#ifndef __ASM_CR_SYSCALL_CODES_H__" >> $@ $(Q) echo "#define __ASM_CR_SYSCALL_CODES_H__" >> $@ + $(Q) echo "/* musl defines loff_t as off_t */" >> $@ + $(Q) echo '#ifndef loff_t' >> $@ + $(Q) echo '#define loff_t off_t' >> $@ + $(Q) echo '#endif' >> $@ $(Q) echo '#include ' >> $@ $(Q) cat $< | awk '/^__NR/{NR32=$$1; \ sub("^__NR", "__NR32", NR32); \ From 0e7321c2fcc5626b45266290b17d9e690d526479 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 12 Jan 2021 08:49:02 +0000 Subject: [PATCH 075/204] compel/test: Fix warn_unused_result MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gcc -O2 -g -Wall -Werror -I ../../../compel/include/uapi -o spy spy.c ../../../compel/libcompel.a spy.c: In function ‘check_pipe_ends’: spy.c:107:2: error: ignoring return value of ‘write’, declared with attribute warn_unused_result [-Werror=unused-result] 107 | write(wfd, "1", 2); | ^~~~~~~~~~~~~~~~~~ spy.c:108:2: error: ignoring return value of ‘read’, declared with attribute warn_unused_result [-Werror=unused-result] 108 | read(rfd, aux, sizeof(aux)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ cc1: all warnings being treated as errors Signed-off-by: Radostin Stoyanov --- compel/test/fdspy/spy.c | 10 ++++++++-- compel/test/rsys/spy.c | 14 +++++++++++--- compel/test/rsys/victim.c | 3 ++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/compel/test/fdspy/spy.c b/compel/test/fdspy/spy.c index c6558f0794..bbb9eb4183 100644 --- a/compel/test/fdspy/spy.c +++ b/compel/test/fdspy/spy.c @@ -104,8 +104,14 @@ static int check_pipe_ends(int wfd, int rfd) } printf("Check pipe ends are connected\n"); - write(wfd, "1", 2); - read(rfd, aux, sizeof(aux)); + if (write(wfd, "1", 2) != 2) { + fprintf(stderr, "write to pipe failed\n"); + return -1; + } + if (read(rfd, aux, sizeof(aux)) != sizeof(aux)) { + fprintf(stderr, "read from pipe failed\n"); + return -1; + } if (aux[0] != '1' || aux[1] != '\0') { fprintf(stderr, "Pipe connectivity lost\n"); return 0; diff --git a/compel/test/rsys/spy.c b/compel/test/rsys/spy.c index 6ccb2a5021..dd89005f12 100644 --- a/compel/test/rsys/spy.c +++ b/compel/test/rsys/spy.c @@ -64,7 +64,9 @@ static inline int chk(int fd, int val) { int v = 0; - read(fd, &v, sizeof(v)); + if (read(fd, &v, sizeof(v)) != sizeof(v)) { + fprintf(stderr, "read failed\n"); + } printf("%d, want %d\n", v, val); return v == val; } @@ -97,7 +99,10 @@ int main(int argc, char **argv) * Kick the victim once */ i = 0; - write(p_in[1], &i, sizeof(i)); + if (write(p_in[1], &i, sizeof(i)) != sizeof(i)) { + fprintf(stderr, "write to pipe failed\n"); + return -1; + } printf("Checking the victim session to be %d\n", sid); pass = chk(p_out[0], sid); @@ -115,7 +120,10 @@ int main(int argc, char **argv) /* * Kick the victim again so it tells new session */ - write(p_in[1], &i, sizeof(i)); + if (write(p_in[1], &i, sizeof(i)) != sizeof(i)) { + fprintf(stderr, "write to pipe failed\n"); + return -1; + } /* * Stop the victim and check the intrusion went well diff --git a/compel/test/rsys/victim.c b/compel/test/rsys/victim.c index 2f1943d0c6..85cb7cb890 100644 --- a/compel/test/rsys/victim.c +++ b/compel/test/rsys/victim.c @@ -9,7 +9,8 @@ int main(int argc, char **argv) break; i = getsid(0); - write(1, &i, sizeof(i)); + if (write(1, &i, sizeof(i)) != sizeof(i)) + break; } return 0; From 4178beaa518e0285bb62daf831054e4de7029d44 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Tue, 15 Dec 2020 10:49:34 +0300 Subject: [PATCH 076/204] servicefd: don't move service fds in case they remain in the same place Improve the check to skip moving service fds in clone_service_fd because we don't need to move anything if old service fds resulting offset is the same as new service fds resulting offset. It saves us from excess calls to dup/fcntl(F_DUPFD). Currently we check that base is the same and shared fdt ids are the same, but there also can be situations where different bases with different shared fdt ids still give the same offset sum (running zdtm in Virtuozzo CT we've seen such a case where service_fd_base=512, new_base=128, service_fd_id=24, id=0, SERVICE_FD_MAX=16). Signed-off-by: Pavel Tikhomirov --- criu/servicefd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/criu/servicefd.c b/criu/servicefd.c index 2533f61680..4aeb15360b 100644 --- a/criu/servicefd.c +++ b/criu/servicefd.c @@ -290,7 +290,8 @@ int clone_service_fd(struct pstree_item *me) if (new_base == -1) return -1; - if (service_fd_base == new_base && service_fd_id == id) + + if (get_service_fd(LOG_FD_OFF) == new_base - LOG_FD_OFF - SERVICE_FD_MAX * id) return 0; /* Dup sfds in memmove() style: they may overlap */ From 3f047f13a845ff7d941a8a7e15195e1603e566d3 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Tue, 10 Nov 2020 11:36:02 +0300 Subject: [PATCH 077/204] util: move open_proc_self_fd to service_fd We need this to avoid conflicts with file descriptors which has to be restored. Currently open_proc PROC_SELF is not used during restoring file descriptors, but we are going to use it for memfd restore. Note: in get_proc_fd let's not close service fd if we detect service fd is not ours, it will be replaced in open_pid_proc anyway, and e.g. in protected sfd context we can't close or open sfd, but can replace it without any problems. While on it also add FIXME because the check in get_proc_fd is error prone in some rare cases (nested pidns is not supported yet). We need to populate this new SELF service fd in populate_pid_proc, so that it is later available in protected context. Also don't close /proc/self service fd in prep_unix_sk_cwd as it can be called from protected context and there is no much point of closing it anyway. Close proc self servicefd in close_old_fds, because first we don't wan't to reuse it from some ancestor, second there can be some junk fd as we are yet only in the beginning of close_old_fds. This junk fd can come from service fds of other tasks from parent's shared fdtable, and this fd would not allow us to do opendir_proc(PROC_SELF). Signed-off-by: Pavel Tikhomirov --- criu/cr-restore.c | 4 ++++ criu/files.c | 9 ++++++++- criu/include/servicefd.h | 2 ++ criu/include/util.h | 2 +- criu/servicefd.c | 10 ++++++++++ criu/sk-unix.c | 1 - criu/util.c | 29 ++++++++++++++++++++--------- 7 files changed, 45 insertions(+), 12 deletions(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 4d98a07900..19ab0c5ae5 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -418,6 +418,10 @@ static int populate_pid_proc(void) pr_err("Can't open PROC_SELF\n"); return -1; } + if (open_pid_proc(PROC_SELF) < 0) { + pr_err("Can't open PROC_SELF\n"); + return -1; + } return 0; } diff --git a/criu/files.c b/criu/files.c index 0912d1a4d6..f10527b591 100644 --- a/criu/files.c +++ b/criu/files.c @@ -1256,6 +1256,14 @@ int close_old_fds(void) struct dirent *de; int fd, ret; + /** + * Close previous /proc/self/ service fd, as we don't wan't to reuse it + * from a different task. Also there can be some junk fd in it's place + * after we've moved our service fds (e.g. from other task of parents + * shared fdtable), we need to close it before opendir_proc() below. + */ + __close_service_fd(PROC_SELF_FD_OFF); + dir = opendir_proc(PROC_SELF, "fd"); if (dir == NULL) return -1; @@ -1297,7 +1305,6 @@ int prepare_fds(struct pstree_item *me) sfds_protected = false; close_service_fd(CGROUP_YARD); sfds_protected = true; - set_proc_self_fd(-1); /* flush any proc cached fds we may have */ if (rsti(me)->fdt) { struct fdt *fdt = rsti(me)->fdt; diff --git a/criu/include/servicefd.h b/criu/include/servicefd.h index c11f89d373..b03bdaf59b 100644 --- a/criu/include/servicefd.h +++ b/criu/include/servicefd.h @@ -17,6 +17,7 @@ enum sfd_type { IMG_STREAMER_FD_OFF, PROC_FD_OFF, /* fd with /proc for all proc_ calls */ PROC_PID_FD_OFF, + PROC_SELF_FD_OFF, CR_PROC_FD_OFF, /* some other's proc fd: * - For dump -- target ns' proc * - For restore -- CRIU ns' proc @@ -44,6 +45,7 @@ extern bool is_service_fd(int fd, enum sfd_type type); extern int service_fd_min_fd(struct pstree_item *item); extern int install_service_fd(enum sfd_type type, int fd); extern int close_service_fd(enum sfd_type type); +extern void __close_service_fd(enum sfd_type type); extern int clone_service_fd(struct pstree_item *me); #endif /* __CR_SERVICE_FD_H__ */ diff --git a/criu/include/util.h b/criu/include/util.h index c2baf2788e..7cb8c262c5 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -180,7 +180,7 @@ extern int cr_daemon(int nochdir, int noclose, int close_fd); extern int status_ready(void); extern int is_root_user(void); -extern void set_proc_self_fd(int fd); +extern int set_proc_self_fd(int fd); static inline bool dir_dots(const struct dirent *de) { diff --git a/criu/servicefd.c b/criu/servicefd.c index 4aeb15360b..952410a8d3 100644 --- a/criu/servicefd.c +++ b/criu/servicefd.c @@ -46,6 +46,7 @@ const char *sfd_type_name(enum sfd_type type) [IMG_FD_OFF] = __stringify_1(IMG_FD_OFF), [PROC_FD_OFF] = __stringify_1(PROC_FD_OFF), [PROC_PID_FD_OFF] = __stringify_1(PROC_PID_FD_OFF), + [PROC_SELF_FD_OFF] = __stringify_1(PROC_SELF_FD_OFF), [CR_PROC_FD_OFF] = __stringify_1(CR_PROC_FD_OFF), [ROOT_FD_OFF] = __stringify_1(ROOT_FD_OFF), [CGROUP_YARD] = __stringify_1(CGROUP_YARD), @@ -206,6 +207,15 @@ int close_service_fd(enum sfd_type type) return 0; } +void __close_service_fd(enum sfd_type type) +{ + int fd; + + fd = __get_service_fd(type, service_fd_id); + close(fd); + clear_bit(type, sfd_map); +} + static int move_service_fd(struct pstree_item *me, int type, int new_id, int new_base) { int old = get_service_fd(type); diff --git a/criu/sk-unix.c b/criu/sk-unix.c index a3964081b8..a5b931b2ad 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -1211,7 +1211,6 @@ static int prep_unix_sk_cwd(struct unix_sk_info *ui, int *prev_cwd_fd, if (switch_ns_by_fd(ns_fd, &mnt_ns_desc, prev_mntns_fd)) return -1; - set_proc_self_fd(-1); close(ns_fd); } diff --git a/criu/util.c b/criu/util.c index 670ef158d6..91add00f36 100644 --- a/criu/util.c +++ b/criu/util.c @@ -281,15 +281,18 @@ int move_fd_from(int *img_fd, int want_fd) static pid_t open_proc_pid = PROC_NONE; static pid_t open_proc_self_pid; -static int open_proc_self_fd = -1; -void set_proc_self_fd(int fd) +int set_proc_self_fd(int fd) { - if (open_proc_self_fd >= 0) - close(open_proc_self_fd); + int ret; + + if (fd < 0) + return close_service_fd(PROC_SELF_FD_OFF); - open_proc_self_fd = fd; open_proc_self_pid = getpid(); + ret = install_service_fd(PROC_SELF_FD_OFF, fd); + + return ret; } static inline int set_proc_pid_fd(int pid, int fd) @@ -308,10 +311,18 @@ static inline int set_proc_pid_fd(int pid, int fd) static inline int get_proc_fd(int pid) { if (pid == PROC_SELF) { - if (open_proc_self_fd != -1 && open_proc_self_pid != getpid()) { - close(open_proc_self_fd); + int open_proc_self_fd; + + open_proc_self_fd = get_service_fd(PROC_SELF_FD_OFF); + /** + * FIXME in case two processes from different pidnses have the + * same pid from getpid() and one inherited service fds from + * another or they share them by shared fdt - this check will + * not detect that one of them reuses /proc/self of another. + * Everything proc related may break in this case. + */ + if (open_proc_self_fd >= 0 && open_proc_self_pid != getpid()) open_proc_self_fd = -1; - } return open_proc_self_fd; } else if (pid == open_proc_pid) return get_service_fd(PROC_PID_FD_OFF); @@ -402,7 +413,7 @@ inline int open_pid_proc(pid_t pid) } if (pid == PROC_SELF) - set_proc_self_fd(fd); + fd = set_proc_self_fd(fd); else fd = set_proc_pid_fd(pid, fd); From 56853fb5354068fef213532aaea4a0ed45d98175 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Fri, 6 Nov 2020 13:40:25 +0300 Subject: [PATCH 078/204] memfd: use PROC_SELF instead of getpid in __open_proc This looks better for me, should be no functional change. Another implication of this is nested pid namespaces, when we will support them "__open_proc(getpid()...)" will try to open file of the process which has the same pid but in NS_ROOT pidns, which is bad. See also aa2d92082 ("files: use PROC_SELF when a process accesses its /proc/PID") for a similar change. Signed-off-by: Pavel Tikhomirov --- criu/memfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/criu/memfd.c b/criu/memfd.c index 4419b4bf53..6c243a509f 100644 --- a/criu/memfd.c +++ b/criu/memfd.c @@ -332,7 +332,7 @@ int memfd_open(struct file_desc *d, u32 *fdflags) * O_LARGEFILE file flag with regular open(). It doesn't seem that * important though. */ - _fd = __open_proc(getpid(), 0, flags, "fd/%d", fd); + _fd = __open_proc(PROC_SELF, 0, flags, "fd/%d", fd); if (_fd < 0) { pr_perror("Can't reopen memfd id=%d", mfe->id); goto err; From 8112e7657e972e44223e4c363db9c183854553bc Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 13 Oct 2020 17:11:52 +0000 Subject: [PATCH 079/204] restore: warning: Value stored to 'ret' is never read criu/cr-restore.c:3230:3: note: Value stored to 'ret' is never read ret = false; ^ ~~~~~ 3228| if (n == -1) { 3229| pr_perror("Failed to get number of supplementary groups"); 3230|-> ret = false; 3231| } 3232| if (n != n_groups) Signed-off-by: Adrian Reber --- criu/cr-restore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 19ab0c5ae5..53eddba6bf 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -3260,7 +3260,7 @@ static bool groups_match(gid_t* groups, int n_groups) n = getgroups(0, NULL); if (n == -1) { pr_perror("Failed to get number of supplementary groups"); - ret = false; + return false; } if (n != n_groups) return false; From 3dc47b22de4b84a120635f9016e662daf601ecd6 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Oct 2020 08:29:13 +0000 Subject: [PATCH 080/204] coverity: get_service_fd() is passed to a parameter that cannot be negative criu/fdstore.c:110: negative_return_fn: Function "get_service_fd(FDSTORE_SK_OFF)" returns a negative number. criu/fdstore.c:110: assign: Assigning: "sk" = "get_service_fd(FDSTORE_SK_OFF)". criu/fdstore.c:114: negative_returns: "sk" is passed to a parameter that cannot be negative. criu/namespaces.c:1366: negative_return_fn: Function "get_service_fd(USERNSD_SK)" returns a negative number. criu/namespaces.c:1366: assign: Assigning: "sk" = "get_service_fd(USERNSD_SK)". criu/namespaces.c:1389: negative_returns: "sk" is passed to a parameter that cannot be negative. Signed-off-by: Adrian Reber Signed-off-by: Andrei Vagin --- criu/fdstore.c | 9 +++++++-- criu/namespaces.c | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/criu/fdstore.c b/criu/fdstore.c index a4583fdf44..7c8eb72081 100644 --- a/criu/fdstore.c +++ b/criu/fdstore.c @@ -107,8 +107,13 @@ int fdstore_add(int fd) int fdstore_get(int id) { - int sk = get_service_fd(FDSTORE_SK_OFF); - int fd; + int sk, fd; + + sk = get_service_fd(FDSTORE_SK_OFF); + if (sk < 0) { + pr_err("Cannot get FDSTORE_SK_OFF fd\n"); + return -1; + } mutex_lock(&desc->lock); if (setsockopt(sk, SOL_SOCKET, SO_PEEK_OFF, &id, sizeof(id))) { diff --git a/criu/namespaces.c b/criu/namespaces.c index c8baf42fc9..eeb9205d01 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -1364,6 +1364,10 @@ int __userns_call(const char *func_name, uns_call_t call, int flags, return call(arg, fd, getpid()); sk = get_service_fd(USERNSD_SK); + if (sk < 0) { + pr_err("Cannot get USERNSD_SK fd\n"); + return -1; + } pr_debug("uns: calling %s (%d, %x)\n", func_name, fd, flags); if (!async) From 41b486790a63d37a22791fbd777f2b053171e0ca Mon Sep 17 00:00:00 2001 From: Valeriy Vdovin Date: Wed, 26 Aug 2020 16:18:41 +0300 Subject: [PATCH 081/204] dump: at exit do not call timing_stop if stats are not initialized Stats often call 'get_timing' function which has a BUG() assertion to catch cases when stats failed to initialize correctly. If stats haven't initialized yet assertion will also be triggered. We dont want the trigger to happen in a case when criu fails at early steps before initializing stats, but this can happen in the following case: - at cr_dump_tasks criu can catch error before the call to init_stats. - it then decides to gracefully quit with error and calls cr_dump_finish. - cr_dump_finish will call timing_stop -> get_timing and BUG() gets triggered But because criu is already quitting gracefully, BUG() is not needed. In this code path we can call timing_stop under proper condition. [avagin: rebase on top of criu-dev and a few minor changes] Signed-off-by: Andrei Vagin --- criu/stats.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/criu/stats.c b/criu/stats.c index 891c378000..ed5a191415 100644 --- a/criu/stats.c +++ b/criu/stats.c @@ -102,6 +102,10 @@ void timing_stop(int t) struct timing *tm; struct timeval now; + /* stats haven't been initialized. */ + if (!dstats && !rstats) + return; + tm = get_timing(t); gettimeofday(&now, NULL); timeval_accumulate(&tm->start, &now, &tm->total); From 504c032af14d35d012916c1c6e3fa1a3e58d9583 Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Fri, 3 Jul 2020 11:31:01 +0300 Subject: [PATCH 082/204] mount: adjust log level for get_clean_mnt In case get_clean_mnt fails open_mountpoint is still able to resolve mounts by helper process or print error in the worst case. Using pr_warn instead of pr_perror. Signed-off-by: Andrey Zhadchenko --- criu/mount.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/criu/mount.c b/criu/mount.c index 2d6ee66dba..d6841b2bd1 100644 --- a/criu/mount.c +++ b/criu/mount.c @@ -1111,8 +1111,8 @@ static char *get_clean_mnt(struct mount_info *mi, char *mnt_path_tmp, char *mnt_ } if (mount(mi->mountpoint, mnt_path, NULL, MS_BIND, NULL)) { - pr_perror("Can't bind-mount %d:%s to %s", - mi->mnt_id, mi->mountpoint, mnt_path); + pr_warn("Can't bind-mount %d:%s to %s: %s\n", + mi->mnt_id, mi->mountpoint, mnt_path, strerror(errno)); rmdir(mnt_path); return NULL; } From d3b1d6e0cac9d72a62e70d3e367192f6bcd4192c Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Fri, 3 Jul 2020 11:42:37 +0300 Subject: [PATCH 083/204] mount: adjust log level for mnt_is_dir mnt_is_dir is used when looking up for suitable mount point. In some cases that function may fail several times. Error level seems to strict for this cases. Added error message to lookup_mnt_sdev in case all mnt_is_dir failed. As for open_handle and alloc_openable which are calling mnt_is_dir, they are used in check_open_handle, which will call error afterwards. Adjusted log level for __open_mountpoint result in open_handle since it is allowed to fail several times. open_handle caller get_mark_path expect possible failure and will print error in case. Signed-off-by: Andrey Zhadchenko --- criu/fsnotify.c | 2 +- criu/mount.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/criu/fsnotify.c b/criu/fsnotify.c index 09093c0bed..f34c6b921d 100644 --- a/criu/fsnotify.c +++ b/criu/fsnotify.c @@ -209,7 +209,7 @@ static int open_handle(unsigned int s_dev, unsigned long i_ino, mntfd = __open_mountpoint(m, -1); if (mntfd < 0) { - pr_err("Can't open mount for s_dev %x, continue\n", s_dev); + pr_warn("Can't open mount for s_dev %x, continue\n", s_dev); continue; } diff --git a/criu/mount.c b/criu/mount.c index d6841b2bd1..d20054aef3 100644 --- a/criu/mount.c +++ b/criu/mount.c @@ -235,6 +235,7 @@ struct mount_info *lookup_mnt_sdev(unsigned int s_dev) if (m->s_dev == s_dev && mnt_is_dir(m)) return m; + pr_err("Unable to find suitable mount point for s_dev %x\n", s_dev); return NULL; } @@ -1016,12 +1017,12 @@ int mnt_is_dir(struct mount_info *pm) mntns_root = mntns_get_root_fd(pm->nsid); if (mntns_root < 0) { - pr_perror("Can't get root fd of mntns for %d", pm->mnt_id); + pr_warn("Can't get root fd of mntns for %d: %s\n", pm->mnt_id, strerror(errno)); return 0; } if (fstatat(mntns_root, pm->ns_mountpoint, &st, 0)) { - pr_perror("Can't fstatat on %s", pm->ns_mountpoint); + pr_warn("Can't fstatat on %s: %s\n", pm->ns_mountpoint, strerror(errno)); return 0; } From 2cf09cc4eafcd61b8d311038da3825ba793ce0ab Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Fri, 3 Jul 2020 12:43:49 +0300 Subject: [PATCH 084/204] fsnotify: rework redundant code open_handle and first part of alloc_openable do the same work. Both these function are called from check_open_handle. Rework check_open_handle to call only alloc_openable. Signed-off-by: Andrey Zhadchenko --- criu/fsnotify.c | 107 +++++++++++++++++++++++++----------------------- 1 file changed, 55 insertions(+), 52 deletions(-) diff --git a/criu/fsnotify.c b/criu/fsnotify.c index f34c6b921d..00a6a32c11 100644 --- a/criu/fsnotify.c +++ b/criu/fsnotify.c @@ -104,12 +104,19 @@ static int open_by_handle(void *arg, int fd, int pid) return syscall(__NR_open_by_handle_at, fd, arg, O_PATH); } +enum { + ERR_NO_MOUNT = -1, + ERR_NO_PATH_IN_MOUNT = -2, + ERR_GENERIC = -3 +}; + static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_handle) { struct mount_info *m; fh_t handle; int fd = -1; char *path; + char suitable_mount_found = 0; decode_handle(&handle, f_handle); @@ -142,6 +149,7 @@ static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_ close(mntfd); if (fd < 0) continue; + suitable_mount_found = 1; if (read_fd_link(fd, buf, sizeof(buf)) < 0) { close(fd); @@ -164,7 +172,7 @@ static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_ if (fstat(openable_fd, &st)) { pr_perror("Can't stat on %s", __path); close(openable_fd); - return ERR_PTR(-errno); + goto err; } close(openable_fd); @@ -175,7 +183,7 @@ static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_ if (st.st_ino == i_ino) { path = xstrdup(buf); if (path == NULL) - return ERR_PTR(-ENOMEM); + return ERR_PTR(ERR_GENERIC); if (root_ns_mask & CLONE_NEWNS) { f_handle->has_mnt_id = true; f_handle->mnt_id = m->mnt_id; @@ -186,9 +194,10 @@ static char *alloc_openable(unsigned int s_dev, unsigned long i_ino, FhEntry *f_ pr_debug("\t\t\tnot openable as %s (%m)\n", __path); } - return ERR_PTR(-ENOENT); err: - return ERR_PTR(-1); + if (suitable_mount_found) + return ERR_PTR(ERR_NO_PATH_IN_MOUNT); + return ERR_PTR(ERR_NO_MOUNT); } static int open_handle(unsigned int s_dev, unsigned long i_ino, @@ -228,63 +237,59 @@ int check_open_handle(unsigned int s_dev, unsigned long i_ino, FhEntry *f_handle) { char *path, *irmap_path; - int fd = -1; + struct mount_info *mi; - if (fault_injected(FI_CHECK_OPEN_HANDLE)) { - fd = -1; + if (fault_injected(FI_CHECK_OPEN_HANDLE)) goto fault; - } - fd = open_handle(s_dev, i_ino, f_handle); -fault: - if (fd >= 0) { - struct mount_info *mi; + /* + * Always try to fetch watchee path first. There are several reasons: + * + * - tmpfs/devtmps do not save inode numbers between mounts, + * so it is critical to have the complete path under our + * hands for restore purpose; + * + * - in case of migration the inodes might be changed as well + * so the only portable solution is to carry the whole path + * to the watchee inside image. + */ + path = alloc_openable(s_dev, i_ino, f_handle); + if (!IS_ERR_OR_NULL(path)) { pr_debug("\tHandle 0x%x:0x%lx is openable\n", s_dev, i_ino); + goto out; + } else if (IS_ERR(path) && PTR_ERR(path) == ERR_NO_MOUNT) { + goto fault; + } else if (IS_ERR(path) && PTR_ERR(path) == ERR_GENERIC) { + goto err; + } - mi = lookup_mnt_sdev(s_dev); - if (mi == NULL) { - pr_err("Unable to lookup a mount by dev 0x%x\n", s_dev); - goto err; - } + mi = lookup_mnt_sdev(s_dev); + if (mi == NULL) { + pr_err("Unable to lookup a mount by dev 0x%x\n", s_dev); + goto err; + } + + if ((mi->fstype->code == FSTYPE__TMPFS) || + (mi->fstype->code == FSTYPE__DEVTMPFS)) { + pr_err("Can't find suitable path for handle (dev %#x ino %#lx): %d\n", + s_dev, i_ino, (int)PTR_ERR(path)); + goto err; + } + if (!opts.force_irmap) /* - * Always try to fetch watchee path first. There are several reasons: + * If we're not forced to do irmap, then + * say we have no path for watch. Otherwise + * do irmap scan even if the handle is + * working. * - * - tmpfs/devtmps do not save inode numbers between mounts, - * so it is critical to have the complete path under our - * hands for restore purpose; - * - * - in case of migration the inodes might be changed as well - * so the only portable solution is to carry the whole path - * to the watchee inside image. + * FIXME -- no need to open-by-handle if + * we are in force-irmap and not on tempfs */ - path = alloc_openable(s_dev, i_ino, f_handle); - if (!IS_ERR_OR_NULL(path)) - goto out; - else if (IS_ERR(path) && PTR_ERR(path) == -ENOMEM) - goto err; - - if ((mi->fstype->code == FSTYPE__TMPFS) || - (mi->fstype->code == FSTYPE__DEVTMPFS)) { - pr_err("Can't find suitable path for handle (dev %#x ino %#lx): %d\n", - s_dev, i_ino, (int)PTR_ERR(path)); - goto err; - } - - if (!opts.force_irmap) - /* - * If we're not forced to do irmap, then - * say we have no path for watch. Otherwise - * do irmap scan even if the handle is - * working. - * - * FIXME -- no need to open-by-handle if - * we are in force-irmap and not on tempfs - */ - goto out_nopath; - } + goto out_nopath; +fault: pr_warn("\tHandle 0x%x:0x%lx cannot be opened\n", s_dev, i_ino); irmap_path = irmap_lookup(s_dev, i_ino); if (!irmap_path) { @@ -298,10 +303,8 @@ int check_open_handle(unsigned int s_dev, unsigned long i_ino, pr_debug("\tDumping %s as path for handle\n", path); f_handle->path = path; out_nopath: - close_safe(&fd); return 0; err: - close_safe(&fd); return -1; } From 11b3a1a75739ccdd4d0c057295108c97f18b9775 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Mon, 25 Jan 2021 19:46:00 -0800 Subject: [PATCH 085/204] workflows/stale: Don't close issue that has labels 'new feature' or 'enhancement' --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 29676b9118..f865bedebd 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -24,4 +24,4 @@ jobs: days-before-close: 365 remove-stale-when-updated: true exempt-pr-labels: 'no-auto-close' - exempt-issue-labels: 'no-auto-close' + exempt-issue-labels: 'no-auto-close', 'new feature', 'enhancement' From 9807413c3959ba4f82ab5b9c5457ac8f4bd42fbf Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 5 Nov 2020 06:47:52 +0000 Subject: [PATCH 086/204] ci: move vagrant test to cirrus ci With Travis dramatically reducing the minutes available for CI, CRIU needs a new place to run tests. This moves the Vagrant based Fedora 32 no VDSO test cases to Cirrus CI. Cirrus CI seems to be one of the very few free CI services allowing access to /dev/kvm. Signed-off-by: Adrian Reber --- .cirrus.yml | 16 ++++++++++++++++ .travis.yml | 1 - scripts/ci/vagrant.sh | 43 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml new file mode 100644 index 0000000000..dce5ce8cdb --- /dev/null +++ b/.cirrus.yml @@ -0,0 +1,16 @@ +environment: + CIRRUS_WORKING_DIR: "/tmp/criu" +container: + # This test case does not work on focal, because the newer version + # of libvirt fails during 'vagrant up' with ip6tables errors. + image: ubuntu:bionic + kvm: true + cpu: 4 + memory: 8G +task: + name: Vagrant Fedora based test (no VDSO) + setup_script: | + scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget + ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto + build_script: | + make -C scripts/ci vagrant-fedora-no-vdso diff --git a/.travis.yml b/.travis.yml index 60516df3a5..562026bf2c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ services: env: - TR_ARCH=local COMPAT_TEST=y - TR_ARCH=local CLANG=1 COMPAT_TEST=y - - TR_ARCH=vagrant-fedora-no-vdso jobs: include: - os: linux diff --git a/scripts/ci/vagrant.sh b/scripts/ci/vagrant.sh index bc10693bb8..a23a371754 100755 --- a/scripts/ci/vagrant.sh +++ b/scripts/ci/vagrant.sh @@ -6,29 +6,55 @@ set -e set -x -VAGRANT_VERSION=2.2.7 +VAGRANT_VERSION=2.2.10 FEDORA_VERSION=32 FEDORA_BOX_VERSION=32.20200422.0 setup() { - apt-get -qq update - # Load the kvm modules for vagrant to use qemu - modprobe kvm kvm_intel + if [ -n "$TRAVIS" ]; then + # Load the kvm modules for vagrant to use qemu + modprobe kvm kvm_intel + fi + if [ -n "$CIRRUS_CI" ]; then + # Running modprobe is not possible on Cirrus, because + # we are running in a container with potentially other + # modules than the host. + # Vagrant can still use /dev/kvm later if we do + chmod 666 /dev/kvm + fi # Tar up the git checkout to have vagrant rsync it to the VM tar cf criu.tar ../../../criu - wget https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/vagrant_${VAGRANT_VERSION}_"$(uname -m)".deb -O /tmp/vagrant.deb && \ + # Cirrus has problems with the following certificate. + wget --no-check-certificate https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/vagrant_${VAGRANT_VERSION}_"$(uname -m)".deb -O /tmp/vagrant.deb && \ dpkg -i /tmp/vagrant.deb - ./apt-install libvirt-bin libvirt-dev qemu-utils qemu - systemctl restart libvirt-bin + ./apt-install libvirt-clients libvirt-daemon-system libvirt-dev qemu-utils qemu \ + ruby build-essential libxml2-dev qemu-kvm rsync ebtables dnsmasq-base \ + openssh-client + if [ -n "$CIRRUS_CI" ]; then + # On Cirrus systemctl does not work, because we are running in + # a container without access to systemd + /usr/sbin/virtlogd -d + /usr/sbin/libvirtd -d + else + systemctl restart libvirtd + fi vagrant plugin install vagrant-libvirt vagrant init fedora/${FEDORA_VERSION}-cloud-base --box-version ${FEDORA_BOX_VERSION} # The default libvirt Vagrant VM uses 512MB. # Travis VMs should have around 7.5GB. # Increasing it to 4GB should work. sed -i Vagrantfile -e 's,^end$, config.vm.provider :libvirt do |libvirt|'"\n"' libvirt.memory = 4096;end'"\n"'end,g' - vagrant up --provider=libvirt + if [ -n "$CIRRUS_CI" ]; then + # Work around for: + # Error while activating network: Call to virNetworkCreate failed: internal error: + # Failed to apply firewall rules /usr/sbin/ip6tables --table filter --list-rules: modprobe: FATAL: Module ip6_tables not found in directory /lib/modules/5.4.0-1025-gcp + # On cirrus-ci.com. Running in a container without access to the host's kernel modules + rm -f /sbin/ip6tables + cp /bin/true /sbin/ip6tables + fi + vagrant up --provider=libvirt > /dev/null mkdir -p /root/.ssh vagrant ssh-config >> /root/.ssh/config ssh default sudo dnf install -y gcc git gnutls-devel nftables-devel libaio-devel \ @@ -45,7 +71,6 @@ fedora-no-vdso() { vagrant reload ssh default cat /proc/cmdline ssh default 'cd /vagrant; tar xf criu.tar; cd criu; make -j 4' - # Excluding two cgroup tests which seem to fail because of cgroup2 ssh default 'cd /vagrant/criu/test; sudo ./zdtm.py run -a --keep-going' } From af1103ff2f4a1cbcfb40cefeb6b195020ccba30e Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Wed, 20 Jan 2021 11:12:51 +0300 Subject: [PATCH 087/204] zdtm: cleanup thread-bomb test error handling and printing 1) Let's do test_init earlier so that max_nr test_msg is now visible in thread-bomb.out. 2) Also lets check errors from malloc and pthread_... functions, print messages about their errors and do proper deallocation at least. Signed-off-by: Pavel Tikhomirov --- test/zdtm/transition/thread-bomb.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/test/zdtm/transition/thread-bomb.c b/test/zdtm/transition/thread-bomb.c index 6621b18ed2..c1b825be7b 100644 --- a/test/zdtm/transition/thread-bomb.c +++ b/test/zdtm/transition/thread-bomb.c @@ -18,17 +18,31 @@ static const size_t stack_size = 64 * 1024; static void *thread_fn(void *arg) { pthread_t t, p, *self; + int err; if (arg) { p = *(pthread_t *)arg; - pthread_join(p, NULL); + err = pthread_join(p, NULL); free(arg); + if (err) { + pr_err("pthread_join(): %d\n", err); + return NULL; + } } self = malloc(sizeof(*self)); + if (!self) { + pr_perror("malloc()"); + return NULL; + } + *self = pthread_self(); - pthread_create(&t, &attr, thread_fn, self); + err = pthread_create(&t, &attr, thread_fn, self); + if (err) { + pr_err("pthread_create(): %d\n", err); + free(self); + } return NULL; } @@ -38,6 +52,8 @@ int main(int argc, char **argv) char *val; int err; + test_init(argc, argv); + err = pthread_attr_init(&attr); if (err) { pr_err("pthread_attr_init(): %d\n", err); @@ -56,8 +72,6 @@ int main(int argc, char **argv) test_msg("%d\n", max_nr); - test_init(argc, argv); - for (i = 0; i < max_nr; i++) { pthread_t p; err = pthread_create(&p, &attr, thread_fn, NULL); From 7766f12e94b9aaad3e6731c23fc4e44bd1ac72f4 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 12 Nov 2020 12:22:41 +0000 Subject: [PATCH 088/204] ci: run aarch64 compile tests on Drone Besides Travis CI Drone CI seems to be only service providing ARM based builds. This switches the aarch64 and arm32 builds to drone.io. Because Drone CI is running in a Docker container we cannot use 'setarch linux32' as it requires the blocked syscall 'personality(2)'. But Drone CI provides an 'arch: arm' which gives the same architecture as 'setarch linux32' on Travis aarch64: armv8l Signed-off-by: Adrian Reber --- .drone.yml | 65 ++++++++++++++++++++++++++++++++++++++ .travis.yml | 10 ------ scripts/ci/run-ci-tests.sh | 10 +++--- 3 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 .drone.yml diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000000..d21b6edbba --- /dev/null +++ b/.drone.yml @@ -0,0 +1,65 @@ +--- +kind: pipeline +type: docker +name: aarch64 build GCC (native) + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: ubuntu:focal + commands: + - scripts/ci/apt-install make + - make -C scripts/ci local + +--- +kind: pipeline +type: docker +name: aarch64 build CLANG (native) + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: ubuntu:focal + commands: + - scripts/ci/apt-install make + - make -C scripts/ci local CLANG=1 + +--- +kind: pipeline +type: docker +name: armhf build GCC (native) + +platform: + os: linux + arch: arm + +steps: +- name: build + # At the time of setting up focal did not work + image: ubuntu:bionic + commands: + - scripts/ci/apt-install make + - make -C scripts/ci local + +--- +kind: pipeline +type: docker +name: armhf build CLANG (native) + +platform: + os: linux + arch: arm + +steps: +- name: build + # At the time of setting up focal did not work + image: ubuntu:bionic + commands: + - scripts/ci/apt-install make + - make -C scripts/ci local CLANG=1 diff --git a/.travis.yml b/.travis.yml index 562026bf2c..10437aa4e4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,16 +33,6 @@ jobs: group: edge virt: vm dist: bionic - - os: linux - arch: arm64 - # This runs on aarch64 with 'setarch linux32' - env: TR_ARCH=armv7hf - dist: bionic - - os: linux - arch: arm64 - # This runs on aarch64 with 'setarch linux32' - env: TR_ARCH=armv7hf CLANG=1 - dist: bionic - os: linux arch: arm64 env: TR_ARCH=fedora-rawhide diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 1a51d6aeb2..900bba5940 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -4,7 +4,8 @@ set -x -e CI_PKGS="protobuf-c-compiler libprotobuf-c-dev libaio-dev libgnutls28-dev libgnutls30 libprotobuf-dev protobuf-compiler libcap-dev libnl-3-dev gdb bash libnet-dev util-linux asciidoctor - libnl-route-3-dev time ccache flake8 libbsd-dev" + libnl-route-3-dev time ccache flake8 libbsd-dev + libperl-dev pkg-config" if [ -e /etc/lsb-release ]; then @@ -51,12 +52,13 @@ ci_prep () { # This can fail on aarch64 travis service apport stop || : - CC=gcc - # clang support if [ "$CLANG" = "1" ]; then - CI_PKGS="$CI_PKGS clang" + # clang support CC=clang + else + CC=gcc fi + CI_PKGS="$CI_PKGS $CC" [ -n "$GCOV" ] && { apt-add-repository -y "ppa:ubuntu-toolchain-r/test" From 76f9ccc70802e2a4cea7f6ca398bfa9a590e0d06 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 29 Dec 2020 08:47:26 +0000 Subject: [PATCH 089/204] ci: also use clang for compel-host-bin Running in an environment with clang and without gcc even installed does not work as compel-host-bin uses HOSTCC which defaults to gcc. If CLANG=1 is set this also sets HOSTCC to clang to actually build compel-host-bin with clang and not with gcc. Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 900bba5940..c64fa11900 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -55,6 +55,10 @@ ci_prep () { if [ "$CLANG" = "1" ]; then # clang support CC=clang + # If this is running in an environment without gcc installed + # compel-host-bin will fail as it is using HOSTCC. Also + # set HOSTCC to clang to build compel-host-bin with it. + export HOSTCC=clang else CC=gcc fi From 90f043dea793bf4f9f0c5547b20dc320b082c6e2 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Wed, 20 Jan 2021 23:48:31 -0800 Subject: [PATCH 090/204] namespaces: handle errors of snprintf Signed-off-by: Andrei Vagin --- criu/namespaces.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/criu/namespaces.c b/criu/namespaces.c index eeb9205d01..ccd6e1323f 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -1163,11 +1163,19 @@ static int write_id_map(pid_t pid, UidGidExtent **extents, int n, char *id_map) * We can perform only a single write (that may contain multiple * newline-delimited records) to a uid_map and a gid_map files. */ - for (i = 0; i < n; i++) - off += snprintf(buf + off, sizeof(buf) - off, + for (i = 0; i < n; i++) { + int len; + + len = snprintf(buf + off, sizeof(buf) - off, "%u %u %u\n", extents[i]->first, extents[i]->lower_first, extents[i]->count); + if (len < 0) { + pr_perror("Unable to form the user/group mappings buffer"); + return -1; + } + off += len; + } fd = open_proc_rw(pid, "%s", id_map); if (fd < 0) From 7d63ceaecdff9b0fe9135b7ac3f626cd5c625f1e Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Wed, 20 Jan 2021 23:49:28 -0800 Subject: [PATCH 091/204] util: zero the events pointer to avoid its double free Signed-off-by: Andrei Vagin --- criu/util.c | 1 + 1 file changed, 1 insertion(+) diff --git a/criu/util.c b/criu/util.c index 91add00f36..634600cecb 100644 --- a/criu/util.c +++ b/criu/util.c @@ -1323,6 +1323,7 @@ int epoll_prepare(int nr_fds, struct epoll_event **events) free_events: xfree(*events); + *events = NULL; return -1; } From 098d4cc721a7687fdd7f122ab11e09eea998e0bc Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Wed, 27 Jan 2021 00:31:27 -0800 Subject: [PATCH 092/204] zdtm: handle a case when a test vma is merged with another one Fixes: #1346 Signed-off-by: Andrei Vagin --- test/zdtm/static/get_smaps_bits.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/zdtm/static/get_smaps_bits.c b/test/zdtm/static/get_smaps_bits.c index 9253f4db6d..3debaa7527 100644 --- a/test/zdtm/static/get_smaps_bits.c +++ b/test/zdtm/static/get_smaps_bits.c @@ -109,7 +109,7 @@ int get_smaps_bits(unsigned long where, unsigned long *flags, unsigned long *mad while (fgets(buf, sizeof(buf), smaps)) { is_vma_range_fmt(buf, &start, &end); - if (!strncmp(buf, "VmFlags: ", 9) && start == where) { + if (!strncmp(buf, "VmFlags: ", 9) && start <= where && where < end) { found = 1; parse_vmflags(buf, flags, madv); break; From d4b0f0f948e6bb0664ba79b6a83d39ecb455c834 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 29 Jan 2021 19:24:55 +0000 Subject: [PATCH 093/204] ci: fix syntax error in stale.yml The commas need to be inside of the quotes. Not on the outside. Signed-off-by: Adrian Reber --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index f865bedebd..e8aa9b4d0d 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -24,4 +24,4 @@ jobs: days-before-close: 365 remove-stale-when-updated: true exempt-pr-labels: 'no-auto-close' - exempt-issue-labels: 'no-auto-close', 'new feature', 'enhancement' + exempt-issue-labels: 'no-auto-close, new feature, enhancement' From 9ec1f1a7be005e2632dce004fbabbddf4c1647b7 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 29 Jan 2021 19:20:48 +0000 Subject: [PATCH 094/204] ci: upgrade vagrant and Fedora version The updates to the latest Vagrant version and from Fedora 32 to 33. Also using --no-tty instead of > /dev/null for vagrant up. Also run 'dnf upgrade -y' in out vagrant VM to get the latest kernel. Signed-off-by: Adrian Reber --- scripts/ci/vagrant.sh | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/ci/vagrant.sh b/scripts/ci/vagrant.sh index a23a371754..3dc79dd839 100755 --- a/scripts/ci/vagrant.sh +++ b/scripts/ci/vagrant.sh @@ -6,9 +6,9 @@ set -e set -x -VAGRANT_VERSION=2.2.10 -FEDORA_VERSION=32 -FEDORA_BOX_VERSION=32.20200422.0 +VAGRANT_VERSION=2.2.14 +FEDORA_VERSION=33 +FEDORA_BOX_VERSION=33.20201019.0 setup() { if [ -n "$TRAVIS" ]; then @@ -54,9 +54,10 @@ setup() { rm -f /sbin/ip6tables cp /bin/true /sbin/ip6tables fi - vagrant up --provider=libvirt > /dev/null + vagrant up --provider=libvirt --no-tty mkdir -p /root/.ssh vagrant ssh-config >> /root/.ssh/config + ssh default sudo dnf upgrade -y ssh default sudo dnf install -y gcc git gnutls-devel nftables-devel libaio-devel \ libasan libcap-devel libnet-devel libnl3-devel make protobuf-c-devel \ protobuf-devel python3-flake8 python3-future python3-protobuf \ From 8c89fbde393c1526c586eb1b98c2b68201638aa1 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sun, 31 Jan 2021 17:30:46 +0000 Subject: [PATCH 095/204] ci: skip bpf tests on vagrant See: https://github.com/checkpoint-restore/criu/issues/1354 Signed-off-by: Adrian Reber --- scripts/ci/vagrant.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/ci/vagrant.sh b/scripts/ci/vagrant.sh index 3dc79dd839..4dccf2613b 100755 --- a/scripts/ci/vagrant.sh +++ b/scripts/ci/vagrant.sh @@ -72,7 +72,9 @@ fedora-no-vdso() { vagrant reload ssh default cat /proc/cmdline ssh default 'cd /vagrant; tar xf criu.tar; cd criu; make -j 4' - ssh default 'cd /vagrant/criu/test; sudo ./zdtm.py run -a --keep-going' + # BPF tests are failing see: https://github.com/checkpoint-restore/criu/issues/1354 + # Needs to be fixed, skip for now + ssh default 'cd /vagrant/criu/test; sudo ./zdtm.py run -a --keep-going -x zdtm/static/bpf_hash -x zdtm/static/bpf_array' } $1 From 442dc651504b8e7a91b74df0d59b39671a3d67ad Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sun, 31 Jan 2021 17:38:45 +0000 Subject: [PATCH 096/204] ci: factor out Fedora Rawhide CI setup To run Fedora Rawhide based aarch64 containers on Drone CI our current Dockerfile setup does not work. This moves the package installation out of the Dockerfile into scripts/ci/prepare-for-fedora-rawhide.sh to be usable in the Dockerfile environment and in the Drone CI environment. Signed-off-by: Adrian Reber --- scripts/build/Dockerfile.fedora.tmpl | 39 ++---------------------- scripts/ci/prepare-for-fedora-rawhide.sh | 37 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 37 deletions(-) create mode 100755 scripts/ci/prepare-for-fedora-rawhide.sh diff --git a/scripts/build/Dockerfile.fedora.tmpl b/scripts/build/Dockerfile.fedora.tmpl index 184f0019af..918849a7b0 100644 --- a/scripts/build/Dockerfile.fedora.tmpl +++ b/scripts/build/Dockerfile.fedora.tmpl @@ -1,42 +1,8 @@ ARG CC=gcc ARG ENV1=FOOBAR -RUN dnf install -y \ - ccache \ - diffutils \ - findutils \ - gcc \ - git \ - gnutls-devel \ - gzip \ - iproute \ - iptables \ - nftables \ - nftables-devel \ - libaio-devel \ - libasan \ - libcap-devel \ - libnet-devel \ - libnl3-devel \ - make \ - procps-ng \ - protobuf-c-devel \ - protobuf-devel \ - python3-flake8 \ - python3-PyYAML \ - python3-future \ - python3-protobuf \ - python3-junit_xml \ - redhat-rpm-config \ - sudo \ - tar \ - which \ - e2fsprogs \ - rubygem-asciidoctor \ - kmod - -RUN ln -sf python3 /usr/bin/python -ENV PYTHON=python3 +COPY scripts/ci/prepare-for-fedora-rawhide.sh /bin/prepare-for-fedora-rawhide.sh +RUN /bin/prepare-for-fedora-rawhide.sh COPY . /criu WORKDIR /criu @@ -49,4 +15,3 @@ RUN mv .ccache /tmp && make mrproper && ccache -sz && \ RUN adduser -u 1000 test RUN make -C test/zdtm -j $(nproc) - diff --git a/scripts/ci/prepare-for-fedora-rawhide.sh b/scripts/ci/prepare-for-fedora-rawhide.sh new file mode 100755 index 0000000000..1b2273b3bd --- /dev/null +++ b/scripts/ci/prepare-for-fedora-rawhide.sh @@ -0,0 +1,37 @@ +#!/bin/bash +set -e -x + +dnf install -y \ + ccache \ + diffutils \ + findutils \ + gcc \ + git \ + gnutls-devel \ + gzip \ + iproute \ + iptables \ + nftables \ + nftables-devel \ + libaio-devel \ + libasan \ + libcap-devel \ + libnet-devel \ + libnl3-devel \ + make \ + procps-ng \ + protobuf-c-devel \ + protobuf-devel \ + python3-flake8 \ + python3-PyYAML \ + python3-future \ + python3-protobuf \ + python3-junit_xml \ + python-unversioned-command \ + redhat-rpm-config \ + sudo \ + tar \ + which \ + e2fsprogs \ + rubygem-asciidoctor \ + kmod From 41efd592edd4d1db62a059de7026503573a67eb9 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sun, 31 Jan 2021 17:41:09 +0000 Subject: [PATCH 097/204] ci: move Fedora Rawhide based tests away from Travis This moves Fedora Rawhide based tests away from Travis. To Github Actions for x86_64 and to Drone for aarch64. Signed-off-by: Adrian Reber --- .drone.yml | 17 +++++++++++++++++ .github/workflows/fedora-rawhide-test.yml | 12 ++++++++++++ .travis.yml | 8 -------- scripts/ci/run-ci-tests.sh | 4 ++++ 4 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 .github/workflows/fedora-rawhide-test.yml diff --git a/.drone.yml b/.drone.yml index d21b6edbba..07eb8be653 100644 --- a/.drone.yml +++ b/.drone.yml @@ -63,3 +63,20 @@ steps: commands: - scripts/ci/apt-install make - make -C scripts/ci local CLANG=1 + +--- +kind: pipeline +type: docker +name: aarch64 Fedora Rawhide + +platform: + os: linux + arch: arm64 + +steps: +- name: build + image: registry.fedoraproject.org/fedora:rawhide + commands: + - scripts/ci/prepare-for-fedora-rawhide.sh + - make -C scripts/ci/ local CC=gcc SKIP_CI_PREP=1 SKIP_CI_TEST=1 CD_TO_TOP=1 + - make -C test/zdtm -j 4 diff --git a/.github/workflows/fedora-rawhide-test.yml b/.github/workflows/fedora-rawhide-test.yml new file mode 100644 index 0000000000..2ff8c1371c --- /dev/null +++ b/.github/workflows/fedora-rawhide-test.yml @@ -0,0 +1,12 @@ +name: Fedora Rawhide Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: Run Fedora Rawhide Test + run: sudo -E make -C scripts/ci fedora-rawhide diff --git a/.travis.yml b/.travis.yml index 10437aa4e4..f51bd08072 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,14 +33,6 @@ jobs: group: edge virt: vm dist: bionic - - os: linux - arch: arm64 - env: TR_ARCH=fedora-rawhide - dist: bionic - - os: linux - arch: amd64 - env: TR_ARCH=fedora-rawhide - dist: bionic - os: linux arch: amd64 env: TR_ARCH=docker-test diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index c64fa11900..7693e5a865 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -138,6 +138,10 @@ print_env ci_prep +if [ "${CD_TO_TOP}" = "1" ]; then + cd ../../ +fi + if [ "$CLANG" = "1" ]; then # Needed for clang on Circle CI LDFLAGS="$LDFLAGS -Wl,-z,now" From b62707bc1a1edc35254e2992a928f53a5fa5efcd Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 29 Jan 2021 18:05:28 +0000 Subject: [PATCH 098/204] Tell podman to use vfs as storage-driver Signed-off-by: Adrian Reber --- scripts/ci/podman-test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ci/podman-test.sh b/scripts/ci/podman-test.sh index d61e2d0b8d..a13e1dbdc2 100755 --- a/scripts/ci/podman-test.sh +++ b/scripts/ci/podman-test.sh @@ -35,6 +35,7 @@ make install # overlaysfs behaves differently on Ubuntu and breaks CRIU # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1857257 +export STORAGE_DRIVER=vfs podman --storage-driver vfs info criu --version From 2cb1156e6afba4baeab5b945b0c15036af3b3a8c Mon Sep 17 00:00:00 2001 From: anatasluo Date: Fri, 29 Jan 2021 13:48:57 +0000 Subject: [PATCH 099/204] vdso: fix segmentation fault caused by char pointer array When I compile criu with "make DEBUG=1" and run it to restore my program, it produces a segmentation fault. In aarch64, with compile flag "-O0", when criu executes the code in pie, it is unable to visit the content of ARCH_VDSO_SYMBOLS. So I put these variables into the stack. Signed-off-by: anatasluo --- criu/arch/aarch64/include/asm/vdso.h | 17 +++++++------- criu/arch/arm/include/asm/vdso.h | 9 +++++--- criu/arch/mips/include/asm/vdso.h | 12 ++++++---- criu/arch/ppc64/include/asm/vdso.h | 34 +++++++++++++++++++--------- criu/arch/s390/include/asm/vdso.h | 17 +++++++++----- criu/arch/x86/include/asm/vdso.h | 23 +++++++++++++------ criu/pie/util-vdso.c | 2 ++ 7 files changed, 75 insertions(+), 39 deletions(-) diff --git a/criu/arch/aarch64/include/asm/vdso.h b/criu/arch/aarch64/include/asm/vdso.h index 8a65e0947c..97a2440eed 100644 --- a/criu/arch/aarch64/include/asm/vdso.h +++ b/criu/arch/aarch64/include/asm/vdso.h @@ -16,15 +16,16 @@ * Workaround for VDSO array symbol table's relocation. * XXX: remove when compel/piegen will support aarch64. */ -static const char* __maybe_unused aarch_vdso_symbol1 = "__kernel_clock_getres"; -static const char* __maybe_unused aarch_vdso_symbol2 = "__kernel_clock_gettime"; -static const char* __maybe_unused aarch_vdso_symbol3 = "__kernel_gettimeofday"; -static const char* __maybe_unused aarch_vdso_symbol4 = "__kernel_rt_sigreturn"; +#define ARCH_VDSO_SYMBOLS_LIST \ + const char* aarch_vdso_symbol1 = "__kernel_clock_getres"; \ + const char* aarch_vdso_symbol2 = "__kernel_clock_gettime"; \ + const char* aarch_vdso_symbol3 = "__kernel_gettimeofday"; \ + const char* aarch_vdso_symbol4 = "__kernel_rt_sigreturn"; -#define ARCH_VDSO_SYMBOLS \ - aarch_vdso_symbol1, \ - aarch_vdso_symbol2, \ - aarch_vdso_symbol3, \ +#define ARCH_VDSO_SYMBOLS \ + aarch_vdso_symbol1, \ + aarch_vdso_symbol2, \ + aarch_vdso_symbol3, \ aarch_vdso_symbol4 extern void write_intraprocedure_branch(unsigned long to, unsigned long from); diff --git a/criu/arch/arm/include/asm/vdso.h b/criu/arch/arm/include/asm/vdso.h index f57790ac28..e96514e0e6 100644 --- a/criu/arch/arm/include/asm/vdso.h +++ b/criu/arch/arm/include/asm/vdso.h @@ -11,8 +11,11 @@ */ #define VDSO_SYMBOL_MAX 2 #define VDSO_SYMBOL_GTOD 1 -#define ARCH_VDSO_SYMBOLS \ - "__vdso_clock_gettime", \ - "__vdso_gettimeofday" +#define ARCH_VDSO_SYMBOLS_LIST \ + const char* aarch_vdso_symbol1 = "__vdso_clock_gettime"; \ + const char* aarch_vdso_symbol2 = "__vdso_gettimeofday"; +#define ARCH_VDSO_SYMBOLS \ + aarch_vdso_symbol1, \ + aarch_vdso_symbol2, #endif /* __CR_ASM_VDSO_H__ */ diff --git a/criu/arch/mips/include/asm/vdso.h b/criu/arch/mips/include/asm/vdso.h index 0e5da159e4..c3e9b01763 100755 --- a/criu/arch/mips/include/asm/vdso.h +++ b/criu/arch/mips/include/asm/vdso.h @@ -14,10 +14,14 @@ */ #define VDSO_SYMBOL_MAX 3 #define VDSO_SYMBOL_GTOD 0 -#define ARCH_VDSO_SYMBOLS \ - "__vdso_clock_gettime", \ - "__vdso_gettimeofday", \ - "__vdso_clock_getres" +#define ARCH_VDSO_SYMBOLS_LIST \ + const char* aarch_vdso_symbol1 = "__vdso_clock_gettime"; \ + const char* aarch_vdso_symbol2 = "__vdso_gettimeofday"; \ + const char* aarch_vdso_symbol3 = "__vdso_clock_getres"; +#define ARCH_VDSO_SYMBOLS \ + aarch_vdso_symbol1, \ + aarch_vdso_symbol2, \ + aarch_vdso_symbol3, #endif /* __CR_ASM_VDSO_H__ */ diff --git a/criu/arch/ppc64/include/asm/vdso.h b/criu/arch/ppc64/include/asm/vdso.h index 6c92348d6d..fe04336650 100644 --- a/criu/arch/ppc64/include/asm/vdso.h +++ b/criu/arch/ppc64/include/asm/vdso.h @@ -14,16 +14,28 @@ */ #define VDSO_SYMBOL_MAX 10 #define VDSO_SYMBOL_GTOD 5 -#define ARCH_VDSO_SYMBOLS \ - "__kernel_clock_getres", \ - "__kernel_clock_gettime", \ - "__kernel_get_syscall_map", \ - "__kernel_get_tbfreq", \ - "__kernel_getcpu", \ - "__kernel_gettimeofday", \ - "__kernel_sigtramp_rt64", \ - "__kernel_sync_dicache", \ - "__kernel_sync_dicache_p5", \ - "__kernel_time" +#define ARCH_VDSO_SYMBOLS_LIST \ + const char* aarch_vdso_symbol1 = "__kernel_clock_getres"; \ + const char* aarch_vdso_symbol2 = "__kernel_clock_gettime"; \ + const char* aarch_vdso_symbol3 = "__kernel_get_syscall_map"; \ + const char* aarch_vdso_symbol4 = "__kernel_get_tbfreq"; \ + const char* aarch_vdso_symbol5 = "__kernel_getcpu"; \ + const char* aarch_vdso_symbol6 = "__kernel_gettimeofday"; \ + const char* aarch_vdso_symbol7 = "__kernel_sigtramp_rt64"; \ + const char* aarch_vdso_symbol8 = "__kernel_sync_dicache"; \ + const char* aarch_vdso_symbol9 = "__kernel_sync_dicache_p5"; \ + const char* aarch_vdso_symbol10 = "__kernel_time"; + +#define ARCH_VDSO_SYMBOLS \ + aarch_vdso_symbol1, \ + aarch_vdso_symbol2, \ + aarch_vdso_symbol3, \ + aarch_vdso_symbol4, \ + aarch_vdso_symbol5, \ + aarch_vdso_symbol6, \ + aarch_vdso_symbol7, \ + aarch_vdso_symbol8, \ + aarch_vdso_symbol9, \ + aarch_vdso_symbol10 #endif /* __CR_ASM_VDSO_H__ */ diff --git a/criu/arch/s390/include/asm/vdso.h b/criu/arch/s390/include/asm/vdso.h index c54d848ad2..ac71f59811 100644 --- a/criu/arch/s390/include/asm/vdso.h +++ b/criu/arch/s390/include/asm/vdso.h @@ -12,13 +12,18 @@ #define VDSO_SYMBOL_GTOD 0 /* - * This definition is used in pie/util-vdso.c to initialize the vdso symbol + * These definitions are used in pie/util-vdso.c to initialize the vdso symbol * name string table 'vdso_symbols' */ -#define ARCH_VDSO_SYMBOLS \ - "__kernel_gettimeofday", \ - "__kernel_clock_gettime", \ - "__kernel_clock_getres", \ - "__kernel_getcpu" +#define ARCH_VDSO_SYMBOLS_LIST \ + const char* aarch_vdso_symbol1 = "__kernel_gettimeofday"; \ + const char* aarch_vdso_symbol2 = "__kernel_clock_gettime"; \ + const char* aarch_vdso_symbol3 = "__kernel_clock_getres"; \ + const char* aarch_vdso_symbol4 = "__kernel_getcpu"; +#define ARCH_VDSO_SYMBOLS \ + aarch_vdso_symbol1, \ + aarch_vdso_symbol2, \ + aarch_vdso_symbol3, \ + aarch_vdso_symbol4 #endif /* __CR_ASM_VDSO_H__ */ diff --git a/criu/arch/x86/include/asm/vdso.h b/criu/arch/x86/include/asm/vdso.h index 28ae2d15a4..54d1fba695 100644 --- a/criu/arch/x86/include/asm/vdso.h +++ b/criu/arch/x86/include/asm/vdso.h @@ -35,13 +35,22 @@ * vsyscall will be patched again when addressing: * https://github.com/checkpoint-restore/criu/issues/512 */ -#define ARCH_VDSO_SYMBOLS \ - "__vdso_clock_gettime", \ - "__vdso_getcpu", \ - "__vdso_gettimeofday", \ - "__vdso_time", \ - "__kernel_sigreturn", \ - "__kernel_rt_sigreturn" + +#define ARCH_VDSO_SYMBOLS_LIST \ + const char* aarch_vdso_symbol1 = "__vdso_clock_gettime"; \ + const char* aarch_vdso_symbol2 = "__vdso_getcpu"; \ + const char* aarch_vdso_symbol3 = "__vdso_gettimeofday"; \ + const char* aarch_vdso_symbol4 = "__vdso_time"; \ + const char* aarch_vdso_symbol5 = "__kernel_sigreturn"; \ + const char* aarch_vdso_symbol6 = "__kernel_rt_sigreturn"; + +#define ARCH_VDSO_SYMBOLS \ + aarch_vdso_symbol1, \ + aarch_vdso_symbol2, \ + aarch_vdso_symbol3, \ + aarch_vdso_symbol4, \ + aarch_vdso_symbol5, \ + aarch_vdso_symbol6 /* "__kernel_vsyscall", */ diff --git a/criu/pie/util-vdso.c b/criu/pie/util-vdso.c index ff91a3b12f..5e1f128e84 100644 --- a/criu/pie/util-vdso.c +++ b/criu/pie/util-vdso.c @@ -219,6 +219,8 @@ static void parse_elf_symbols(uintptr_t mem, size_t size, Phdr_t *load, struct vdso_symtable *t, uintptr_t dynsymbol_names, Hash_t *hash, Dyn_t *dyn_symtab) { + ARCH_VDSO_SYMBOLS_LIST + const char *vdso_symbols[VDSO_SYMBOL_MAX] = { ARCH_VDSO_SYMBOLS }; From 5792612d3199863db18694bb3d49460f912cb441 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 1 Feb 2021 13:23:49 +0000 Subject: [PATCH 100/204] ci: move asan and image streamer test to github Signed-off-by: Adrian Reber --- .github/workflows/fedora-asan-test.yml | 12 ++++++++++++ .github/workflows/stream-test.yml | 12 ++++++++++++ .travis.yml | 5 ----- scripts/build/Dockerfile.fedora-asan.hdr | 2 +- scripts/ci/Makefile | 2 +- 5 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/fedora-asan-test.yml create mode 100644 .github/workflows/stream-test.yml diff --git a/.github/workflows/fedora-asan-test.yml b/.github/workflows/fedora-asan-test.yml new file mode 100644 index 0000000000..44b0f16d6e --- /dev/null +++ b/.github/workflows/fedora-asan-test.yml @@ -0,0 +1,12 @@ +name: Fedora ASAN Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: Run Fedora ASAN Test + run: sudo -E make -C scripts/ci fedora-asan diff --git a/.github/workflows/stream-test.yml b/.github/workflows/stream-test.yml new file mode 100644 index 0000000000..ecdd81e0a3 --- /dev/null +++ b/.github/workflows/stream-test.yml @@ -0,0 +1,12 @@ +name: CRIU Image Streamer Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: Run CRIU Image Streamer Test + run: sudo -E make -C scripts/ci local STREAM_TEST=1 diff --git a/.travis.yml b/.travis.yml index f51bd08072..a3b6049882 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,11 +43,6 @@ jobs: # On xenial it should be possible to test overlayfs; # broken on the latest bionic kernel dist: xenial - - os: linux - arch: amd64 - env: TR_ARCH=fedora-asan - dist: bionic - - env: TR_ARCH=local STREAM_TEST=1 allow_failures: - env: TR_ARCH=docker-test - env: TR_ARCH=docker-test DIST=xenial diff --git a/scripts/build/Dockerfile.fedora-asan.hdr b/scripts/build/Dockerfile.fedora-asan.hdr index 3ec09c1c00..7a20edd243 100644 --- a/scripts/build/Dockerfile.fedora-asan.hdr +++ b/scripts/build/Dockerfile.fedora-asan.hdr @@ -1,2 +1,2 @@ -FROM fedora:29 +FROM registry.fedoraproject.org/fedora:latest ENV ASAN=1 diff --git a/scripts/ci/Makefile b/scripts/ci/Makefile index ffa78446a2..79637db0b3 100644 --- a/scripts/ci/Makefile +++ b/scripts/ci/Makefile @@ -60,7 +60,7 @@ $(TARGETS): restart-docker fedora-asan: restart-docker $(MAKE) -C ../build $@$(target-suffix) - docker run -it $(CONTAINER_OPTS) criu-$@ ./scripts/ci/asan.sh $(ZDTM_OPTIONS) + docker run $(CONTAINER_OPTS) criu-$@ ./scripts/ci/asan.sh $(ZDTM_OPTIONS) docker-test: ./docker-test.sh From 10cb8521da1af12ff8b3875a9023b8c92e983f95 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 1 Feb 2021 11:17:39 +0000 Subject: [PATCH 101/204] README.md: remove trailing whitespaces Signed-off-by: Adrian Reber --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d703638ec4..ae721e2df1 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ CRIU (stands for Checkpoint and Restore in Userspace) is a utility to checkpoint/restore Linux tasks. -Using this tool, you can freeze a running application (or part of it) and checkpoint +Using this tool, you can freeze a running application (or part of it) and checkpoint it to a hard drive as a collection of files. You can then use the files to restore and run the application from the point it was frozen at. The distinctive feature of the CRIU project is that it is mainly implemented in user space. There are some more projects -doing C/R for Linux, and so far CRIU [appears to be](https://criu.org/Comparison_to_other_CR_projects) +doing C/R for Linux, and so far CRIU [appears to be](https://criu.org/Comparison_to_other_CR_projects) the most feature-rich and up-to-date with the kernel. CRIU project is (almost) the never-ending story, because we have to always keep up with the @@ -20,8 +20,8 @@ looking for contributors of all kinds -- feedback, bug reports, testing, coding, Please refer to [CONTRIBUTING.md](CONTRIBUTING.md) if you would like to get involved. The project [started](https://criu.org/History) as the way to do live migration for OpenVZ -Linux containers, but later grew to more sophisticated and flexible tool. It is currently -used by (integrated into) OpenVZ, LXC/LXD, Docker, and other software, project gets tremendous +Linux containers, but later grew to more sophisticated and flexible tool. It is currently +used by (integrated into) OpenVZ, LXC/LXD, Docker, and other software, project gets tremendous help from the community, and its packages are included into many Linux distributions. The project home is at http://criu.org. This wiki contains all the knowledge base for CRIU we have. @@ -31,13 +31,13 @@ Pages worth starting with are: - [Examples of more advanced usage](https://criu.org/Category:HOWTO) - Troubleshooting can be hard, some help can be found [here](https://criu.org/When_C/R_fails), [here](https://criu.org/What_cannot_be_checkpointed) and [here](https://criu.org/FAQ) -### Checkpoint and restore of simple loop process +### Checkpoint and restore of simple loop process [

](https://asciinema.org/a/232445) ## Advanced features As main usage for CRIU is live migration, there's a library for it called P.Haul. Also the -project exposes two cool core features as standalone libraries. These are libcompel for parasite code +project exposes two cool core features as standalone libraries. These are libcompel for parasite code injection and libsoccr for TCP connections checkpoint-restore. ### Live migration From 4c3f3245e0b0e972229b70e9b0a0996e7b731b54 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 1 Feb 2021 11:37:36 +0000 Subject: [PATCH 102/204] README.md: remove unused badges; add a few new badges Signed-off-by: Adrian Reber --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae721e2df1..ee8987f3c7 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -[![master](https://travis-ci.org/checkpoint-restore/criu.svg?branch=master)](https://travis-ci.org/checkpoint-restore/criu) -[![development](https://travis-ci.org/checkpoint-restore/criu.svg?branch=criu-dev)](https://travis-ci.org/checkpoint-restore/criu) -[![Codacy Badge](https://api.codacy.com/project/badge/Grade/55251ec7db28421da4481fc7c1cb0cee)](https://www.codacy.com/app/xemul/criu?utm_source=github.com&utm_medium=referral&utm_content=xemul/criu&utm_campaign=Badge_Grade) +![X86_64 GCC Test](https://github.com/checkpoint-restore/criu/workflows/X86_64%20GCC%20Test/badge.svg) +![Podman Test](https://github.com/checkpoint-restore/criu/workflows/Podman%20Test/badge.svg) +[![CircleCI](https://circleci.com/gh/checkpoint-restore/criu.svg?style=svg)](https://circleci.com/gh/checkpoint-restore/criu) +

## CRIU -- A project to implement checkpoint/restore functionality for Linux From 81c3c9748a29b9b1825b88612ed03d85eea136ab Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 1 Feb 2021 11:06:07 +0000 Subject: [PATCH 103/204] ci: move compat tests to Github Actions Signed-off-by: Adrian Reber --- .github/workflows/compat-test.yml | 16 ++++++++++++++++ .travis.yml | 4 ---- scripts/ci/run-ci-tests.sh | 1 + 3 files changed, 17 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/compat-test.yml diff --git a/.github/workflows/compat-test.yml b/.github/workflows/compat-test.yml new file mode 100644 index 0000000000..5ae25fb73e --- /dev/null +++ b/.github/workflows/compat-test.yml @@ -0,0 +1,16 @@ +name: Compat Tests + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + strategy: + matrix: + target: [GCC, CLANG] + + + steps: + - uses: actions/checkout@v2 + - name: Run Compat Tests (${{ matrix.target }}) + run: sudo -E make -C scripts/ci local COMPAT_TEST=y ${{ matrix.target }}=1 diff --git a/.travis.yml b/.travis.yml index a3b6049882..c908b341ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,6 @@ dist: bionic cache: ccache services: - docker -env: - - TR_ARCH=local COMPAT_TEST=y - - TR_ARCH=local CLANG=1 COMPAT_TEST=y jobs: include: - os: linux @@ -46,7 +43,6 @@ jobs: allow_failures: - env: TR_ARCH=docker-test - env: TR_ARCH=docker-test DIST=xenial - - env: TR_ARCH=fedora-rawhide - env: TR_ARCH=local GCOV=1 script: - sudo make CCACHE=1 -C scripts/ci $TR_ARCH diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 7693e5a865..197020eb27 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -188,6 +188,7 @@ if [ "${COMPAT_TEST}x" = "yx" ] ; then done # shellcheck disable=SC2086 apt-get remove $INCOMPATIBLE_LIBS + dpkg --add-architecture i386 scripts/ci/apt-install "$IA32_PKGS" mkdir -p /usr/lib/x86_64-linux-gnu/ mv "$REFUGE"/* /usr/lib/x86_64-linux-gnu/ From 7a64074c0b899b98e0d5f438e8d3fa2f7706ed3b Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Mon, 1 Feb 2021 03:43:57 +0300 Subject: [PATCH 104/204] dump: dump has to fail if there is locks and --file-locks isn't set If criu finds a file lock and the --file-locks option isn't set, it stops dumping processes, resumes them and exits with an error. Signed-off-by: Andrei Vagin --- criu/file-lock.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/criu/file-lock.c b/criu/file-lock.c index 8be7589df3..3b3c4759b8 100644 --- a/criu/file-lock.c +++ b/criu/file-lock.c @@ -108,6 +108,12 @@ int dump_file_locks(void) continue; } + if (!opts.handle_file_locks) { + pr_err("Some file locks are hold by dumping tasks!" + "You can try --" OPT_FILE_LOCKS " to dump them.\n"); + return -1; + } + file_lock_entry__init(&fle); fle.pid = fl->real_owner; fle.fd = fl->owners_fd; From 3fb8cd3a4d68f3c0479ed124760ad8a65e16e596 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Mon, 1 Feb 2021 03:41:18 +0300 Subject: [PATCH 105/204] test/zdtm: check that locks are not dumped if --file-locks isn't set If criu finds a file lock and the --file-locks option isn't set, it stops dumping processes, resumes them and exits with an error. Signed-off-by: Andrei Vagin --- test/zdtm/static/Makefile | 1 + test/zdtm/static/file_locks00_fail.c | 1 + test/zdtm/static/file_locks00_fail.desc | 1 + 3 files changed, 3 insertions(+) create mode 120000 test/zdtm/static/file_locks00_fail.c create mode 100644 test/zdtm/static/file_locks00_fail.desc diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index aae49832a7..0e14e9d089 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -302,6 +302,7 @@ TST_FILE = \ file_lease03 \ file_lease04 \ file_locks00 \ + file_locks00_fail \ file_locks01 \ file_locks02 \ file_locks03 \ diff --git a/test/zdtm/static/file_locks00_fail.c b/test/zdtm/static/file_locks00_fail.c new file mode 120000 index 0000000000..d523748259 --- /dev/null +++ b/test/zdtm/static/file_locks00_fail.c @@ -0,0 +1 @@ +file_locks00.c \ No newline at end of file diff --git a/test/zdtm/static/file_locks00_fail.desc b/test/zdtm/static/file_locks00_fail.desc new file mode 100644 index 0000000000..6626fefa80 --- /dev/null +++ b/test/zdtm/static/file_locks00_fail.desc @@ -0,0 +1 @@ +{'flags': 'excl crfail'} From 042560a2fdcfe722e8864e47e119e2c69c0b002e Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 1 Feb 2021 11:08:24 +0000 Subject: [PATCH 106/204] ci: move coverage run to github This also connects the coverage run to codecov.io. Signed-off-by: Adrian Reber --- .github/workflows/gcov-test.yml | 14 ++++++++++++++ .travis.yml | 1 - Makefile | 5 +++++ scripts/ci/run-ci-tests.sh | 11 +++++------ 4 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/gcov-test.yml diff --git a/.github/workflows/gcov-test.yml b/.github/workflows/gcov-test.yml new file mode 100644 index 0000000000..f1b38e77e6 --- /dev/null +++ b/.github/workflows/gcov-test.yml @@ -0,0 +1,14 @@ +name: Coverage Tests + +on: [push, pull_request] + +jobs: + build: + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: Run Coverage Tests + run: sudo -E make -C scripts/ci local GCOV=1 + - name: Run Coverage Analysis + run: sudo -E make codecov diff --git a/.travis.yml b/.travis.yml index c908b341ad..b9b5c643ad 100644 --- a/.travis.yml +++ b/.travis.yml @@ -43,7 +43,6 @@ jobs: allow_failures: - env: TR_ARCH=docker-test - env: TR_ARCH=docker-test DIST=xenial - - env: TR_ARCH=local GCOV=1 script: - sudo make CCACHE=1 -C scripts/ci $TR_ARCH after_success: diff --git a/Makefile b/Makefile index ed1544315a..6b7972efe4 100644 --- a/Makefile +++ b/Makefile @@ -413,6 +413,11 @@ lint: shellcheck scripts/*.sh shellcheck scripts/ci/*.sh scripts/ci/apt-install +codecov: SHELL := $(shell which bash) +codecov: + bash <(curl -s https://codecov.io/bash) +.PHONY: codecov + include Makefile.install .DEFAULT_GOAL := all diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 197020eb27..57cab6ab12 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -64,12 +64,6 @@ ci_prep () { fi CI_PKGS="$CI_PKGS $CC" - [ -n "$GCOV" ] && { - apt-add-repository -y "ppa:ubuntu-toolchain-r/test" - scripts/ci/apt-install --no-install-suggests g++-7 - CC=gcc-7 - } - # ccache support, only enable for non-GCOV case if [ "$CCACHE" = "1" ] && [ -z "$GCOV" ]; then # ccache is installed by default, need to set it up @@ -291,5 +285,10 @@ make -C test/others/libcriu run # external namespace testing make -C test/others/ns_ext run +# Skip all further tests when running with GCOV=1 +# The one test which currently cannot handle GCOV testing is compel/test +# Probably because the GCOV Makefile infrastructure does not exist in compel +[ -n "$GCOV" ] && exit 0 + # compel testing make -C compel/test From 9546f391926c2e4fc165e84d9e3af2cda3c7249d Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Mon, 25 Jan 2021 10:21:14 +0300 Subject: [PATCH 107/204] files: Don't forget on stripping deleted postfix on linked files Otherwise we gonna accumulated "(deleted)" postfix generated by kernel on every c/r iteration eventually overflowing PATH_MAX which will make container undumpable. Signed-off-by: Cyrill Gorcunov --- criu/files-reg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/criu/files-reg.c b/criu/files-reg.c index aed1e73dc2..b9d67146cb 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -1301,9 +1301,11 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, * name. */ - if (errno == ENOENT) + if (errno == ENOENT) { + strip_deleted(link); return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id, nsid); + } pr_perror("Can't stat path"); return -1; From 8d92d4694808f96c6646da0a912169e6f05f2e9d Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Mon, 11 Jan 2021 17:57:05 +0300 Subject: [PATCH 108/204] files-reg: rework strip_deleted Moved strip_deleted to util and reworked it so other parts of criu can use it without the need of files-reg.h Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Pavel Tikhomirov Signed-off-by: Andrey Zhadchenko --- criu/files-reg.c | 42 ++++------------------------------------ criu/include/files-reg.h | 6 +++++- criu/include/util.h | 2 ++ criu/memfd.c | 2 +- criu/proc_parse.c | 26 ++++++++++++------------- criu/util.c | 33 +++++++++++++++++++++++++++++++ 6 files changed, 57 insertions(+), 54 deletions(-) diff --git a/criu/files-reg.c b/criu/files-reg.c index b9d67146cb..f4f41193b2 100644 --- a/criu/files-reg.c +++ b/criu/files-reg.c @@ -1150,40 +1150,6 @@ static inline bool nfs_silly_rename(char *rpath, const struct fd_parms *parms) return (parms->fs_type == NFS_SUPER_MAGIC) && is_sillyrename_name(rpath); } -int strip_deleted(struct fd_link *link) -{ - struct dcache_prepends { - const char *str; - size_t len; - } static const prepends[] = { - { - .str = " (deleted)", - .len = 10, - }, { - .str = "//deleted", - .len = 9, - } - }; - size_t i; - - for (i = 0; i < ARRAY_SIZE(prepends); i++) { - size_t at; - - if (link->len <= prepends[i].len) - continue; - - at = link->len - prepends[i].len; - if (!strcmp(&link->name[at], prepends[i].str)) { - pr_debug("Strip '%s' tag from '%s'\n", - prepends[i].str, link->name); - link->name[at] = '\0'; - link->len -= prepends[i].len; - return 1; - } - } - return 0; -} - static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, int lfd, u32 id, struct ns_id *nsid) { @@ -1219,7 +1185,7 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, * cases. */ if (pid != 0) { - bool is_dead = strip_deleted(link); + bool is_dead = link_strip_deleted(link); mntns_root = mntns_get_root_fd(nsid); if (mntns_root < 0) return -1; @@ -1252,7 +1218,7 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, * this FS and can't have a valid " (deleted)" * postfix as a part of not deleted filename. */ - strip_deleted(link); + link_strip_deleted(link); /* * Devpts devices/files are generated by the * kernel itself so we should not try to generate @@ -1269,7 +1235,7 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, * be careful whether anybody still has any of its hardlinks * also open. */ - strip_deleted(link); + link_strip_deleted(link); return dump_ghost_remap(rpath + 1, ost, lfd, id, nsid); } @@ -1302,7 +1268,7 @@ static int check_path_remap(struct fd_link *link, const struct fd_parms *parms, */ if (errno == ENOENT) { - strip_deleted(link); + link_strip_deleted(link); return dump_linked_remap(rpath + 1, plen - 1, ost, lfd, id, nsid); } diff --git a/criu/include/files-reg.h b/criu/include/files-reg.h index 016d76a9fc..0cb67c51ad 100644 --- a/criu/include/files-reg.h +++ b/criu/include/files-reg.h @@ -2,6 +2,7 @@ #define __CR_FILES_REG_H__ #include "files.h" +#include "util.h" #include "images/regfile.pb-c.h" #include "images/ghost-file.pb-c.h" @@ -51,7 +52,10 @@ extern void free_link_remaps(void); extern int prepare_remaps(void); extern int try_clean_remaps(bool only_ghosts); -extern int strip_deleted(struct fd_link *link); +static inline int link_strip_deleted(struct fd_link *link) +{ + return strip_deleted(link->name, link->len); +} extern int dead_pid_conflict(void); diff --git a/criu/include/util.h b/criu/include/util.h index 7cb8c262c5..311fa85ff3 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -252,6 +252,8 @@ static inline bool issubpath(const char *path, const char *sub_path) (end == '/' || end == '\0'); } +int strip_deleted(char *path, int len); + /* * mkdir -p */ diff --git a/criu/memfd.c b/criu/memfd.c index 6c243a509f..48245eb752 100644 --- a/criu/memfd.c +++ b/criu/memfd.c @@ -157,7 +157,7 @@ static int dump_one_memfd(int lfd, u32 id, const struct fd_parms *p) } else link = p->link; - strip_deleted(link); + link_strip_deleted(link); /* link->name is always started with "." which has to be skipped. */ if (strncmp(link->name + 1, MEMFD_PREFIX, MEMFD_PREFIX_LEN) == 0) name = &link->name[1 + MEMFD_PREFIX_LEN]; diff --git a/criu/proc_parse.c b/criu/proc_parse.c index ba60832f45..83ad0194e7 100644 --- a/criu/proc_parse.c +++ b/criu/proc_parse.c @@ -35,7 +35,6 @@ #include "seccomp.h" #include "string.h" #include "namespaces.h" -#include "files-reg.h" #include "cgroup.h" #include "cgroup-props.h" #include "timerfd.h" @@ -306,16 +305,15 @@ static int vma_get_mapfile_user(const char *fname, struct vma_area *vma, vfi_dev = makedev(vfi->dev_maj, vfi->dev_min); if (is_memfd(vfi_dev)) { - struct fd_link link; - link.len = strlen(fname); - strlcpy(link.name, fname, sizeof(link.name)); - strip_deleted(&link); + char tmp[PATH_MAX]; + strlcpy(tmp, fname, PATH_MAX); + strip_deleted(tmp, strlen(tmp)); /* * The error EPERM will be shown in the following pr_perror(). * It comes from the previous open() call. */ - pr_perror("Can't open mapped [%s]", link.name); + pr_perror("Can't open mapped [%s]", tmp); /* * TODO Perhaps we could do better than failing and dump the @@ -1351,10 +1349,10 @@ static void cure_path(char *path) static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname) { - struct fd_link root_link; unsigned int kmaj, kmin; - int ret, n; + int ret, n, len; char *sub, *opt = NULL; + char link_path[PATH_MAX]; new->mountpoint = xmalloc(PATH_MAX); if (new->mountpoint == NULL) @@ -1371,14 +1369,14 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname) cure_path(new->mountpoint); cure_path(new->root); - root_link.len = strlen(new->root); - if (root_link.len >= sizeof(root_link.name) - 1) { - pr_err("new root path (%s) exceeds %zu\n", new->root, sizeof(root_link.name)); + len = strlen(new->root); + if (len >= PATH_MAX - 1) { + pr_err("new root path (%s) exceeds %d\n", new->root, PATH_MAX); goto err; } - strcpy(root_link.name, new->root); - if (strip_deleted(&root_link)) { - strcpy(new->root, root_link.name); + strcpy(link_path, new->root); + if (strip_deleted(link_path, len)) { + strcpy(new->root, link_path); new->deleted = true; } diff --git a/criu/util.c b/criu/util.c index 634600cecb..1c3070e9a2 100644 --- a/criu/util.c +++ b/criu/util.c @@ -1414,3 +1414,36 @@ int mount_detached_fs(const char *fsname) return fd; } +int strip_deleted(char *name, int len) +{ + struct dcache_prepends { + const char *str; + size_t len; + } static const prepends[] = { + { + .str = " (deleted)", + .len = 10, + }, { + .str = "//deleted", + .len = 9, + } + }; + size_t i; + + for (i = 0; i < ARRAY_SIZE(prepends); i++) { + size_t at; + + if (len <= prepends[i].len) + continue; + + at = len - prepends[i].len; + if (!strcmp(&name[at], prepends[i].str)) { + pr_debug("Strip '%s' tag from '%s'\n", + prepends[i].str, name); + name[at] = '\0'; + len -= prepends[i].len; + return 1; + } + } + return 0; +} From a4c000e30500994baace2a3e0b4756e8117b80d0 Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Mon, 11 Jan 2021 18:17:40 +0300 Subject: [PATCH 109/204] sk-unix: make criu respect existing files while restoring ghost unix socket fd If there are any file in place of ghost unix socket, criu will delete it at restore while trying to recreate ghost one. Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Pavel Tikhomirov Signed-off-by: Andrey Zhadchenko --- criu/sk-unix.c | 80 ++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/criu/sk-unix.c b/criu/sk-unix.c index a5b931b2ad..09ae1f542f 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -1470,56 +1470,49 @@ static int bind_on_deleted(int sk, struct unix_sk_info *ui) addr.sun_family = AF_UNIX; memcpy(&addr.sun_path, ui->name, ui->ue->name.len); - ret = bind(sk, (struct sockaddr *)&addr, - sizeof(addr.sun_family) + ui->ue->name.len); - if (ret < 0) { + ret = access(ui->name, F_OK); + if (!ret) { + snprintf(path_parked, sizeof(path_parked), UNIX_GHOST_FMT, ui->name); /* - * In case if there some real living socket - * with same name just move it aside for a - * while, we will move it back once ghost - * socket is processed. + * In case if there exist any file with same name + * just move it aside for a while, we will move it back + * once ghost socket is processed. */ - if (errno == EADDRINUSE) { - snprintf(path_parked, sizeof(path_parked), UNIX_GHOST_FMT, ui->name); - /* - * Say previous restore get killed in a middle due to - * any reason, be ready the file might already exist, - * clean it up. - */ - if (unlinkat(AT_FDCWD, path_parked, 0) == 0) - pr_debug("ghost: Unlinked stale socket id %#x ino %u name %s\n", - ui->ue->id, ui->ue->ino, path_parked); - if (rename(ui->name, path_parked)) { - ret = -errno; - pr_perror("ghost: Can't rename id %#x ino %u addr %s -> %s", - ui->ue->id, ui->ue->ino, ui->name, path_parked); - return ret; - } - pr_debug("ghost: id %#x ino %u renamed %s -> %s\n", - ui->ue->id, ui->ue->ino, ui->name, path_parked); - renamed = true; - ret = bind(sk, (struct sockaddr *)&addr, - sizeof(addr.sun_family) + ui->ue->name.len); - } - if (ret < 0) { + if (unlinkat(AT_FDCWD, path_parked, 0) == 0) + pr_debug("ghost: Unlinked stale socket id %#x ino %d name %s\n", + ui->ue->id, ui->ue->ino, path_parked); + if (rename(ui->name, path_parked)) { ret = -errno; - pr_perror("ghost: Can't bind on socket id %#x ino %u addr %s", - ui->ue->id, ui->ue->ino, ui->name); + pr_perror("ghost: Can't rename id %#x ino %u addr %s -> %s", + ui->ue->id, ui->ue->ino, ui->name, path_parked); return ret; } + pr_debug("ghost: id %#x ino %d renamed %s -> %s\n", + ui->ue->id, ui->ue->ino, ui->name, path_parked); + renamed = true; + } + + ret = bind(sk, (struct sockaddr *)&addr, + sizeof(addr.sun_family) + ui->ue->name.len); + if (ret < 0) { + ret = -errno; + pr_perror("ghost: Can't bind on socket id %#x ino %d addr %s", + ui->ue->id, ui->ue->ino, ui->name); + goto out_rename; } ret = restore_file_perms(ui); if (ret < 0) - return ret; + goto out; ret = keep_deleted(ui); if (ret < 0) { pr_err("ghost: Can't save socket %#x ino %u addr %s into fdstore\n", ui->ue->id, ui->ue->ino, ui->name); - return -EIO; + ret = -EIO; } +out: /* * Once everything is ready, just remove the socket from the * filesystem and rename back the original one if it were here. @@ -1529,19 +1522,18 @@ static int bind_on_deleted(int sk, struct unix_sk_info *ui) ret = -errno; pr_perror("ghost: Can't unlink socket %#x ino %u addr %s", ui->ue->id, ui->ue->ino, ui->name); - return ret; } +out_rename: if (renamed) { if (rename(path_parked, ui->name)) { ret = -errno; pr_perror("ghost: Can't rename id %#x ino %u addr %s -> %s", ui->ue->id, ui->ue->ino, path_parked, ui->name); - return ret; + } else { + pr_debug("ghost: id %#x ino %d renamed %s -> %s\n", + ui->ue->id, ui->ue->ino, path_parked, ui->name); } - - pr_debug("ghost: id %#x ino %u renamed %s -> %s\n", - ui->ue->id, ui->ue->ino, path_parked, ui->name); } /* @@ -1988,6 +1980,7 @@ static struct file_desc_ops unix_desc_ops = { static int unlink_sk(struct unix_sk_info *ui) { int ret = 0, cwd_fd = -1, root_fd = -1, ns_fd = -1; + struct stat statbuf; if (!ui->name || ui->name[0] == '\0' || (ui->ue->uflags & USK_EXTERN)) return 0; @@ -1995,6 +1988,15 @@ static int unlink_sk(struct unix_sk_info *ui) if (prep_unix_sk_cwd(ui, &cwd_fd, &root_fd, NULL)) return -1; + ret = stat(ui->name, &statbuf); + if (!ret) { + /* Do not cleanup non-socket files */ + if (!S_ISSOCK(statbuf.st_mode)) { + ret = 0; + goto out; + } + } + ret = unlinkat(AT_FDCWD, ui->name, 0) ? -1 : 0; if (ret < 0 && errno != ENOENT) { pr_warn("Can't unlink socket %u peer %u (name %s dir %s)\n", From 82f2033080cb49e57d26698008c3ae5760965bd4 Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Mon, 9 Nov 2020 08:07:28 +0300 Subject: [PATCH 110/204] sk-unix: rework unix_resolve_name Use SIOCUNIXFILE ioctl approach to get socket fd opened with O_PATH. Utilise it for detecting deletion and resolving relative name. Preserve old method as fallback if this new IOCTL fails. Also remove overmount_sock crfail in zdtm. With the unix_resolve_name reworked to use SIOCUNIXFILE criu can now pass this test. Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Pavel Tikhomirov Signed-off-by: Andrey Zhadchenko --- criu/include/util.h | 1 + criu/sk-unix.c | 80 +++++++++++++++++++++++++++- criu/util.c | 40 ++++++++++++++ test/zdtm/static/overmount_sock.desc | 2 +- 4 files changed, 121 insertions(+), 2 deletions(-) diff --git a/criu/include/util.h b/criu/include/util.h index 311fa85ff3..f000e97a74 100644 --- a/criu/include/util.h +++ b/criu/include/util.h @@ -253,6 +253,7 @@ static inline bool issubpath(const char *path, const char *sub_path) } int strip_deleted(char *path, int len); +int cut_path_ending(char *path, char *sub_path); /* * mkdir -p diff --git a/criu/sk-unix.c b/criu/sk-unix.c index 09ae1f542f..25d25e2d4c 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -559,7 +559,7 @@ const struct fdtype_ops unix_dump_ops = { .dump = dump_one_unix_fd, }; -static int unix_resolve_name(int lfd, uint32_t id, struct unix_sk_desc *d, +static int unix_resolve_name_old(int lfd, uint32_t id, struct unix_sk_desc *d, UnixSkEntry *ue, const struct fd_parms *p) { char *name = d->name; @@ -644,6 +644,84 @@ static int unix_resolve_name(int lfd, uint32_t id, struct unix_sk_desc *d, goto out; } +static int unix_resolve_name(int lfd, uint32_t id, struct unix_sk_desc *d, + UnixSkEntry *ue, const struct fd_parms *p) +{ + char *name = d->name; + char path[PATH_MAX], tmp[PATH_MAX]; + struct stat st; + int fd, proc_fd, mnt_id, ret; + + if (d->namelen == 0 || name[0] == '\0') + return 0; + + if (kdat.sk_unix_file && (root_ns_mask & CLONE_NEWNS)) { + if (get_mnt_id(lfd, &mnt_id)) + return -1; + ue->mnt_id = mnt_id; + ue->has_mnt_id = true; + } + + fd = ioctl(lfd, SIOCUNIXFILE); + if (fd < 0) { + pr_warn("Unable to get a socket file descriptor with SIOCUNIXFILE ioctl."); + goto fallback; + } + + ret = fstat(fd, &st); + if (ret) { + pr_perror("Unable to fstat socket fd"); + return -1; + } + d->mode = st.st_mode; + d->uid = st.st_uid; + d->gid = st.st_gid; + + proc_fd = get_service_fd(PROC_FD_OFF); + if (proc_fd < 0) { + pr_err("Unable to get service fd for proc\n"); + return -1; + } + + snprintf(tmp, sizeof(tmp), "self/fd/%d", fd); + ret = readlinkat(proc_fd, tmp, path, PATH_MAX); + if (ret < 0 && ret >= PATH_MAX) { + pr_perror("Unable to readlink %s", tmp); + goto out; + } + path[ret] = 0; + + d->deleted = strip_deleted(path, ret); + + if (name[0] != '/') { + ret = cut_path_ending(path, name); + if (ret) { + pr_err("Unable too resolve %s from %s\n", name, path); + goto out; + } + + ue->name_dir = xstrdup(path); + if (!ue->name_dir) { + ret = -ENOMEM; + goto out; + } + + pr_debug("Resolved socket relative name %s to %s/%s\n", name, ue->name_dir, name); + } + + ret = 0; +out: + close(fd); + return ret; + +fallback: + pr_warn("Trying to resolve unix socket with obsolete method"); + ret = unix_resolve_name_old(lfd, id, d, ue, p); + if (ret < 0) + pr_err("Unable to resolve unix socket name with obsolete method. Try a linux kernel newer than 4.10\n"); + return ret; +} + /* * Returns: < 0 on error, 0 if OK, 1 to skip the socket */ diff --git a/criu/util.c b/criu/util.c index 1c3070e9a2..76624dc5ac 100644 --- a/criu/util.c +++ b/criu/util.c @@ -1447,3 +1447,43 @@ int strip_deleted(char *name, int len) } return 0; } + +/* + * This function check if path ends with ending and cuts it from path. + * Return 0 if path is cut. -1 otherwise, leaving path unchanged. + * Example: + * path = "/foo/bar", ending = "bar" + * cut(path, ending) -> path becomes "/foo" + * + * 1. Skip leading "./" in subpath. + * 2. Respect root: ("/a/b", "b") -> "/a" but ("/a", "a") -> "/" + * 3. Refuse to cut identical strings, e.g. ("abc", "abc") will result in -1 + * 4. Do not handle "..", "//", "./" (with exception "./" as leading symbols) + */ + +int cut_path_ending(char *path, char *ending) +{ + int ending_pos; + + if (ending[0] == '.' && ending[1] == '/') + ending = ending + 2; + + ending_pos = strlen(path) - strlen(ending); + + if (ending_pos < 1) + return -1; + + if (strcmp(path + ending_pos, ending)) + return -1; + + if (path[ending_pos - 1] != '/') + return -1; + + if (ending_pos == 1) { + path[ending_pos] = 0; + return 0; + } + + path[ending_pos - 1] = 0; + return 0; +} \ No newline at end of file diff --git a/test/zdtm/static/overmount_sock.desc b/test/zdtm/static/overmount_sock.desc index 1ba68c314d..cc9d23ab9f 100644 --- a/test/zdtm/static/overmount_sock.desc +++ b/test/zdtm/static/overmount_sock.desc @@ -1 +1 @@ -{'flavor' : 'ns uns', 'flags': 'suid crfail'} +{'flavor' : 'ns uns', 'flags': 'suid'} From 903b903d22a572250c99a54dc6305300bd3f6db4 Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Fri, 18 Sep 2020 00:35:48 +0300 Subject: [PATCH 111/204] zdtm: add fifo upon unix socket test case Create unix socket and unlink it. Make fifo in this place. Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Pavel Tikhomirov Signed-off-by: Andrey Zhadchenko --- test/zdtm/static/Makefile | 1 + test/zdtm/static/fifo_upon_unix_socket.c | 150 ++++++++++++++++++++ test/zdtm/static/fifo_upon_unix_socket.desc | 1 + 3 files changed, 152 insertions(+) create mode 100644 test/zdtm/static/fifo_upon_unix_socket.c create mode 100644 test/zdtm/static/fifo_upon_unix_socket.desc diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index 0e14e9d089..78ba8f017c 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -315,6 +315,7 @@ TST_FILE = \ netns-nft \ maps_file_prot \ socket_close_data01 \ + fifo_upon_unix_socket \ TST_DIR = \ cwd00 \ diff --git a/test/zdtm/static/fifo_upon_unix_socket.c b/test/zdtm/static/fifo_upon_unix_socket.c new file mode 100644 index 0000000000..d7cf878e29 --- /dev/null +++ b/test/zdtm/static/fifo_upon_unix_socket.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "zdtmtst.h" + +const char *test_doc = "Check that fifo upon ghost socket configuration is restored"; +const char *test_author = "Andrey Zhadchenko "; + +char *filename; +TEST_OPTION(filename, string, "socket name", 1); + +static int fill_sock_name(struct sockaddr_un *name, const char *filename) +{ + char *cwd; + + cwd = get_current_dir_name(); + if (strlen(filename) + strlen(cwd) + 1 >= sizeof(name->sun_path)) { + pr_err("Name %s/%s is too long for socket\n", + cwd, filename); + return -1; + } + + name->sun_family = AF_LOCAL; + ssprintf(name->sun_path, "%s/%s", cwd, filename); + return 0; +} + +static int sk_alloc_bind(int type, struct sockaddr_un *addr) +{ + int sk; + + sk = socket(PF_UNIX, type, 0); + if (sk < 0) { + pr_perror("socket"); + return -1; + } + + if (addr && bind(sk, (const struct sockaddr *)addr, sizeof(*addr))) { + pr_perror("bind %s", addr->sun_path); + close(sk); + return -1; + } + + return sk; +} + +static int sk_alloc_connect(int type, struct sockaddr_un *addr) +{ + int sk; + + sk = socket(PF_UNIX, type, 0); + if (sk < 0) { + pr_perror("socket"); + return -1; + } + + if (connect(sk, (const struct sockaddr *)addr, sizeof(*addr))) { + pr_perror("connect %s", addr->sun_path); + close(sk); + return -1; + } + + return sk; +} + +static int check_fd(int fdin, int fdout) +{ + int ret; + char c = 0; + + ret = write(fdin, &c, 1); + if (ret != 1) + goto err; + + ret = read(fdout, &c, 1); + if (ret != 1) + goto err; + + return 0; + +err: + pr_perror("broken fd pair %d %d", fdin, fdout); + return -1; +} + +int main(int argc, char **argv) +{ + int sk1, sk2, fd1, err; + struct sockaddr_un addr; + + test_init(argc, argv); + + unlink(filename); + + if (fill_sock_name(&addr, filename)) + return 1; + + sk1 = sk_alloc_bind(SOCK_DGRAM, &addr); + if (sk1 < 0) { + pr_perror("Can't create sk"); + return 1; + } + + sk2 = sk_alloc_connect(SOCK_DGRAM, &addr); + if (sk2 < 0) { + pr_perror("Can't connect to sk"); + return 1; + } + + if (unlink(filename) < 0) { + fail("can't unlink %s", filename); + return 1; + } + + if (mkfifo(filename, 0666)) { + pr_perror("can't make fifo \"%s\"", filename); + return 1; + } + + fd1 = open(filename, O_RDWR); + if (fd1 < 0) { + pr_perror("can't open %s", filename); + return 1; + } + + test_daemon(); + test_waitsig(); + + unlink(filename); + + err = check_fd(sk2, sk1) || check_fd(fd1, fd1); + if (err) + fail(); + else + pass(); + + close(sk1); + close(sk2); + close(fd1); + + return 0; +} diff --git a/test/zdtm/static/fifo_upon_unix_socket.desc b/test/zdtm/static/fifo_upon_unix_socket.desc new file mode 100644 index 0000000000..2eac7e654b --- /dev/null +++ b/test/zdtm/static/fifo_upon_unix_socket.desc @@ -0,0 +1 @@ +{'flags': 'suid'} From 1b5dbe56785c26f34cade4efdf5886fb8cd75832 Mon Sep 17 00:00:00 2001 From: Andrey Zhadchenko Date: Mon, 9 Nov 2020 08:22:45 +0300 Subject: [PATCH 112/204] zdtm: add second fifo_upon_unix test This differs from the previous one by 1. using relative path instead of absolute 2. chdir() after setup Reviewed-by: Alexander Mikhalitsyn Reviewed-by: Pavel Tikhomirov Signed-off-by: Andrey Zhadchenko --- test/zdtm/static/Makefile | 5 ++++- ...unix_socket.c => fifo_upon_unix_socket00.c} | 18 ++++++++++++++++++ ...ocket.desc => fifo_upon_unix_socket00.desc} | 0 test/zdtm/static/fifo_upon_unix_socket01.c | 1 + test/zdtm/static/fifo_upon_unix_socket01.desc | 1 + 5 files changed, 24 insertions(+), 1 deletion(-) rename test/zdtm/static/{fifo_upon_unix_socket.c => fifo_upon_unix_socket00.c} (87%) rename test/zdtm/static/{fifo_upon_unix_socket.desc => fifo_upon_unix_socket00.desc} (100%) create mode 120000 test/zdtm/static/fifo_upon_unix_socket01.c create mode 120000 test/zdtm/static/fifo_upon_unix_socket01.desc diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index 78ba8f017c..d0974bb0dd 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -315,7 +315,8 @@ TST_FILE = \ netns-nft \ maps_file_prot \ socket_close_data01 \ - fifo_upon_unix_socket \ + fifo_upon_unix_socket00 \ + fifo_upon_unix_socket01 \ TST_DIR = \ cwd00 \ @@ -593,6 +594,8 @@ thread_different_uid_gid: LDLIBS += -pthread -lcap bpf_hash: LDLIBS += -lbpf bpf_array: LDLIBS += -lbpf +fifo_upon_unix_socket01: CFLAGS += -DFIFO_UPON_UNIX01 + $(LIB): force $(Q) $(MAKE) -C $(LIBDIR) diff --git a/test/zdtm/static/fifo_upon_unix_socket.c b/test/zdtm/static/fifo_upon_unix_socket00.c similarity index 87% rename from test/zdtm/static/fifo_upon_unix_socket.c rename to test/zdtm/static/fifo_upon_unix_socket00.c index d7cf878e29..f75965fdd7 100644 --- a/test/zdtm/static/fifo_upon_unix_socket.c +++ b/test/zdtm/static/fifo_upon_unix_socket00.c @@ -17,6 +17,7 @@ const char *test_author = "Andrey Zhadchenko "; char *filename; TEST_OPTION(filename, string, "socket name", 1); +#ifndef FIFO_UPON_UNIX01 static int fill_sock_name(struct sockaddr_un *name, const char *filename) { char *cwd; @@ -32,6 +33,19 @@ static int fill_sock_name(struct sockaddr_un *name, const char *filename) ssprintf(name->sun_path, "%s/%s", cwd, filename); return 0; } +#else +static int fill_sock_name(struct sockaddr_un *name, const char *filename) +{ + if (strlen(filename) + 1 >= sizeof(name->sun_path)) { + pr_err("Name %s is too long for socket\n", filename); + return -1; + } + + name->sun_family = AF_LOCAL; + ssprintf(name->sun_path, "%s", filename); + return 0; +} +#endif static int sk_alloc_bind(int type, struct sockaddr_un *addr) { @@ -131,6 +145,10 @@ int main(int argc, char **argv) return 1; } +#ifdef FIFO_UPON_UNIX01 + chdir("/"); +#endif + test_daemon(); test_waitsig(); diff --git a/test/zdtm/static/fifo_upon_unix_socket.desc b/test/zdtm/static/fifo_upon_unix_socket00.desc similarity index 100% rename from test/zdtm/static/fifo_upon_unix_socket.desc rename to test/zdtm/static/fifo_upon_unix_socket00.desc diff --git a/test/zdtm/static/fifo_upon_unix_socket01.c b/test/zdtm/static/fifo_upon_unix_socket01.c new file mode 120000 index 0000000000..235241eb30 --- /dev/null +++ b/test/zdtm/static/fifo_upon_unix_socket01.c @@ -0,0 +1 @@ +fifo_upon_unix_socket00.c \ No newline at end of file diff --git a/test/zdtm/static/fifo_upon_unix_socket01.desc b/test/zdtm/static/fifo_upon_unix_socket01.desc new file mode 120000 index 0000000000..d29414c1d5 --- /dev/null +++ b/test/zdtm/static/fifo_upon_unix_socket01.desc @@ -0,0 +1 @@ +fifo_upon_unix_socket00.desc \ No newline at end of file From 42c211285cd2a7cc1bb1b92a3d1233978b644c2c Mon Sep 17 00:00:00 2001 From: Nicolas Viennot Date: Tue, 9 Feb 2021 20:26:34 +0000 Subject: [PATCH 113/204] seccomp: initialize seccomp_mode in all cases In parse_pid_status(), it is assumed that the seccomp field can be missing from /proc/pid/status. When the field is missing, it is not properly initialized, leading to bad behavior. We initialize seccomp_mode to SECCOMP_MODE_DISABLED by default, similarly to what is done in compel/src/lib/infect.c:parse_pid_status. Signed-off-by: Nicolas Viennot --- criu/proc_parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/criu/proc_parse.c b/criu/proc_parse.c index 83ad0194e7..7b0b32e2e7 100644 --- a/criu/proc_parse.c +++ b/criu/proc_parse.c @@ -1056,6 +1056,7 @@ int parse_pid_status(pid_t pid, struct seize_task_status *ss, void *data) cr->s.sigpnd = 0; cr->s.shdpnd = 0; + cr->s.seccomp_mode = SECCOMP_MODE_DISABLED; if (bfdopenr(&f)) return -1; From a277c84936218c76371403b67d4df2192a1c5776 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 17 Feb 2021 17:03:10 +0000 Subject: [PATCH 114/204] ci: use runc instead of crun for podman tests The latest podman pulls in crun instead of runc. Unfortunately crun is not built against libcriu and does not support checkpoint/restore. Switch back to runc. Signed-off-by: Adrian Reber --- scripts/ci/podman-test.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/ci/podman-test.sh b/scripts/ci/podman-test.sh index a13e1dbdc2..5d8a6f8400 100755 --- a/scripts/ci/podman-test.sh +++ b/scripts/ci/podman-test.sh @@ -23,7 +23,10 @@ apt-get -y purge docker-ce || : curl \ software-properties-common -./apt-install podman containernetworking-plugins +# explicitly install runc. crun is not compiled with criu support +./apt-install cri-o-runc podman containernetworking-plugins + +echo -e '[engine]\nruntime="runc"' > /etc/containers/containers.conf export SKIP_CI_TEST=1 From 2692215a5fe252915ad39c01651aa1f57b909e37 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Fri, 19 Feb 2021 04:14:53 +0000 Subject: [PATCH 115/204] file-lock: Add space in error message Signed-off-by: Radostin Stoyanov --- criu/file-lock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/criu/file-lock.c b/criu/file-lock.c index 3b3c4759b8..050954cdec 100644 --- a/criu/file-lock.c +++ b/criu/file-lock.c @@ -109,7 +109,7 @@ int dump_file_locks(void) } if (!opts.handle_file_locks) { - pr_err("Some file locks are hold by dumping tasks!" + pr_err("Some file locks are hold by dumping tasks! " "You can try --" OPT_FILE_LOCKS " to dump them.\n"); return -1; } @@ -201,7 +201,7 @@ static int lock_check_fd(int lfd, struct file_lock *fl) } else { /* * The ret == 0 means, that new lock doesn't conflict - * with any others on the file. But since we do know, + * with any others on the file. But since we do know, * that there should be some other one (file is found * in /proc/locks), it means that the lock is already * on file pointed by fd. From 89aa87484e0eef41bb51c5fb2751b8852346ba0a Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Fri, 19 Feb 2021 04:18:36 +0000 Subject: [PATCH 116/204] javaTests: Add --file-locks option Resolves #1370 Signed-off-by: Radostin Stoyanov --- test/javaTests/src/org/criu/java/tests/CheckpointRestore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/javaTests/src/org/criu/java/tests/CheckpointRestore.java b/test/javaTests/src/org/criu/java/tests/CheckpointRestore.java index 9d61e126f1..860619c267 100644 --- a/test/javaTests/src/org/criu/java/tests/CheckpointRestore.java +++ b/test/javaTests/src/org/criu/java/tests/CheckpointRestore.java @@ -361,7 +361,7 @@ String copyFiles() throws IOException { private void checkpoint(String pid, String checkpointOpt) throws IOException, InterruptedException { ProcessBuilder builder; System.out.println("Checkpointing process " + pid); - String command = "../../criu/criu dump --shell-job -t " + pid + " -vvv -D " + logFolder + " -o dump.log"; + String command = "../../criu/criu dump --shell-job -t " + pid + " --file-locks -v4 -D " + logFolder + " -o dump.log"; if (0 == checkpointOpt.length()) { String[] cmd = command.split(" "); builder = new ProcessBuilder(cmd); @@ -411,7 +411,7 @@ private void checkpoint(String pid, String checkpointOpt) throws IOException, In private void restore(String restoreOpt) throws IOException, InterruptedException { ProcessBuilder builder; System.out.println("Restoring process"); - String command = "../../criu/criu restore -d -vvv --shell-job -D " + logFolder + " -o restore.log"; + String command = "../../criu/criu restore -d --file-locks -v4 --shell-job -D " + logFolder + " -o restore.log"; if (0 == restoreOpt.length()) { String[] cmd = command.split(" "); builder = new ProcessBuilder(cmd); From 7a8f426f152f2449bea9106eac055b5d9c97f048 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Fri, 19 Feb 2021 04:07:07 +0000 Subject: [PATCH 117/204] test: Reduce verbosity of mvn output The -q option will only show errors Signed-off-by: Radostin Stoyanov --- scripts/build/Dockerfile.openj9-alpine | 2 +- scripts/build/Dockerfile.openj9-ubuntu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/build/Dockerfile.openj9-alpine b/scripts/build/Dockerfile.openj9-alpine index 39ea4d08e6..873284f44a 100644 --- a/scripts/build/Dockerfile.openj9-alpine +++ b/scripts/build/Dockerfile.openj9-alpine @@ -26,5 +26,5 @@ WORKDIR /criu RUN make -ENTRYPOINT mvn -f test/javaTests/pom.xml test +ENTRYPOINT mvn -q -f test/javaTests/pom.xml test diff --git a/scripts/build/Dockerfile.openj9-ubuntu b/scripts/build/Dockerfile.openj9-ubuntu index 0663eb7ccf..abcd8cc1a1 100644 --- a/scripts/build/Dockerfile.openj9-ubuntu +++ b/scripts/build/Dockerfile.openj9-ubuntu @@ -29,5 +29,5 @@ WORKDIR /criu RUN make -ENTRYPOINT mvn -f test/javaTests/pom.xml test +ENTRYPOINT mvn -q -f test/javaTests/pom.xml test From 6110236b6d343a63053f80a41acb29e847b76de1 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Fri, 19 Feb 2021 04:20:56 +0000 Subject: [PATCH 118/204] zdtm: Add javaTests output to .gitignore Signed-off-by: Radostin Stoyanov --- test/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/.gitignore b/test/.gitignore index 6a735ba7ae..17b4d8635f 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -14,3 +14,5 @@ /zdtm_mount_cgroups.lock /compel/handle_binary /umount2 +/javaTests/output/ +/javaTests/target/ From 42171caba4e4101e62f5b039ec9bc36bac3b6880 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 17 Feb 2021 16:58:50 +0000 Subject: [PATCH 119/204] test: fix test compilation on rawhide The latest glibc has redefined SIGSTKSZ as 'sysconf (_SC_SIGSTKSZ)' and this breaks a static char[] definition. Hardcoding TESTSIGSTKSZ to 16384 in the test. This fixes: sigaltstack.c:17:13: error: variably modified 'stack_thread' at file scope 17 | static char stack_thread[SIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__; | ^~~~~~~~~~~~ sigaltstack.c:18:13: error: variably modified 'stack_main' at file scope 18 | static char stack_main[SIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__; | ^~~~~~~~~~ Signed-off-by: Adrian Reber --- test/zdtm/static/sigaltstack.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/zdtm/static/sigaltstack.c b/test/zdtm/static/sigaltstack.c index f36d409f5e..13602d3a1b 100644 --- a/test/zdtm/static/sigaltstack.c +++ b/test/zdtm/static/sigaltstack.c @@ -14,8 +14,10 @@ const char *test_doc = "Check for alternate signal stack"; const char *test_author = "Cyrill Gorcunov "; -static char stack_thread[SIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__; -static char stack_main[SIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__; +#define TESTSIGSTKSZ 16384 + +static char stack_thread[TESTSIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__; +static char stack_main[TESTSIGSTKSZ + TEST_MSG_BUFFER_SIZE] __stack_aligned__; enum { SAS_MAIN_OLD, From 950a88c741dbf511bb94b8cbfccb1a77286ff40c Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 23 Feb 2021 22:08:27 -0800 Subject: [PATCH 120/204] bug: add __builtin_unreachable in BUG_ON_HANDLER This will surpress false gcc warnings like this: criu/stats.c:85:10: error: array subscript 4 is above array bounds of 'struct timing[2]' [-Werror=array-bounds] 85 | return &rstats->timings[t]; | ^~~~~~~~~~~~~~~~~~~ criu/stats.c:25:16: note: while referencing 'timings' 25 | struct timing timings[RESTORE_TIME_NS_STATS]; | ^~~~~~~ cc1: all warnings being treated as errors Signed-off-by: Andrei Vagin --- include/common/bug.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/common/bug.h b/include/common/bug.h index 4622911040..bacbf566b8 100644 --- a/include/common/bug.h +++ b/include/common/bug.h @@ -24,6 +24,7 @@ pr_err("BUG at %s:%d\n", __FILE__, __LINE__); \ __raise(); \ *(volatile unsigned long *)NULL = 0xdead0000 + __LINE__; \ + __builtin_unreachable(); \ } \ } while (0) #else From 3397ac0a7c0c20cbc1126ad80d4d86e28731988e Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Tue, 23 Feb 2021 22:12:58 -0800 Subject: [PATCH 121/204] sk-unix: check whether a socket name is NULL before printing it criu/include/log.h:72:2: error: '%s' directive argument is null [-Werror=format-overflow=] 72 | print_on_level(LOG_DEBUG, \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 73 | LOG_PREFIX fmt, ##__VA_ARGS__) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ criu/sk-unix.c:133:2: note: in expansion of macro 'pr_debug' 133 | pr_debug("\t%s: ino %u peer_ino %u family %4d type %4d state %2d name %s\n", | ^~~~~~~~ CC criu/stats.o Fixes: #1373 Signed-off-by: Andrei Vagin --- criu/sk-unix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/criu/sk-unix.c b/criu/sk-unix.c index 25d25e2d4c..e589da8deb 100644 --- a/criu/sk-unix.c +++ b/criu/sk-unix.c @@ -131,7 +131,8 @@ static struct unix_sk_listen_icon *lookup_unix_listen_icons(unsigned int peer_in static void show_one_unix(char *act, const struct unix_sk_desc *sk) { pr_debug("\t%s: ino %u peer_ino %u family %4d type %4d state %2d name %s\n", - act, sk->sd.ino, sk->peer_ino, sk->sd.family, sk->type, sk->state, sk->name); + act, sk->sd.ino, sk->peer_ino, sk->sd.family, sk->type, sk->state, + sk->name ? : "null"); if (sk->nr_icons) { int i; From ab395e423cf85f3980aac3d36b4079136255cb86 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Thu, 25 Feb 2021 15:44:12 +0300 Subject: [PATCH 122/204] plugin: check for plugin path truncation New compilators print warnings if snprintf return value is not checked for truncation. Let's make them happy. Fixes: #1372 Signed-off-by: Pavel Tikhomirov --- criu/plugin.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/criu/plugin.c b/criu/plugin.c index b97d3763a9..f35a04fc95 100644 --- a/criu/plugin.c +++ b/criu/plugin.c @@ -243,7 +243,11 @@ int cr_plugin_init(int stage) if (len < 3 || strncmp(de->d_name + len - 3, ".so", 3)) continue; - snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name); + if (snprintf(path, sizeof(path), "%s/%s", opts.libdir, de->d_name) >= + sizeof(path)) { + pr_err("Unable to build plugin path\n"); + goto err; + } if (cr_lib_load(stage, path)) goto err; From 168668ec75e004327d1778a3b1875c870541506f Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 1 Mar 2021 15:58:22 +0000 Subject: [PATCH 123/204] ci: fix Fedora rawhide CI failures It seems the Fedora rawhide /tmp is no longer 1777 but 755. Change it back to 1777 to make our CI runs successful again. Signed-off-by: Adrian Reber --- scripts/ci/prepare-for-fedora-rawhide.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/ci/prepare-for-fedora-rawhide.sh b/scripts/ci/prepare-for-fedora-rawhide.sh index 1b2273b3bd..3ce991dc42 100755 --- a/scripts/ci/prepare-for-fedora-rawhide.sh +++ b/scripts/ci/prepare-for-fedora-rawhide.sh @@ -35,3 +35,6 @@ dnf install -y \ e2fsprogs \ rubygem-asciidoctor \ kmod + +# /tmp is no longer 755 in the rawhide container image and breaks CI - fix it +chmod 1777 /tmp From e0d4aef3518aba3abef9e811b1551ce7dedd5447 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Mon, 1 Mar 2021 23:12:22 -0800 Subject: [PATCH 124/204] github/stale: separate labels with commas without following spaces Signed-off-by: Andrei Vagin --- .github/workflows/stale.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index e8aa9b4d0d..beb6774e4b 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -24,4 +24,4 @@ jobs: days-before-close: 365 remove-stale-when-updated: true exempt-pr-labels: 'no-auto-close' - exempt-issue-labels: 'no-auto-close, new feature, enhancement' + exempt-issue-labels: 'no-auto-close,new feature,enhancement' From f8cf0715e23147c24775fdce398a42f3dc7407c1 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 26 Feb 2021 20:43:41 +0000 Subject: [PATCH 125/204] ci/compat: Check if tests are 32-bit ELFs To be sure that we don't lose COMPAT_TEST=y on the way to make. Signed-off-by: Dmitry Safonov --- scripts/ci/run-ci-tests.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 57cab6ab12..b568ff43f1 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -190,6 +190,11 @@ fi time make CC="$CC" -j4 -C test/zdtm V=1 +if [ "${COMPAT_TEST}x" = "yx" ] ; then + # Cross-verify that zdtm tests are 32-bit + file test/zdtm/static/env00 | grep 'ELF 32-bit' -q +fi + [ -f "$CCACHE_LOGFILE" ] && cat "$CCACHE_LOGFILE" # umask has to be called before a first criu run, so that .gcda (coverage data) From 84be3047ad77b80df480610e284dbff03784428d Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 12 Nov 2020 03:10:52 +0000 Subject: [PATCH 126/204] x86: Use PTRACE_GET_THREAD_AREA instead of sys_get_thread_area() To minimize things done in parasite, PTRACE_GET_THREAD_AREA can be used to get remote tls. That also removes an additional compat stack (de)allocation in the parasite (also asm-coded syscall). In order to use PTRACE_GET_THREAD_AREA, the dumpee should be stopped. So, let's move this from criu to compel to non-seized state and put tls into thread info on x86. Signed-off-by: Dmitry Safonov --- compel/Makefile | 4 + .../src/lib/include/uapi/asm/infect-types.h | 5 ++ .../src/lib/include/uapi/asm/infect-types.h | 5 ++ .../src/lib/include/uapi/asm/infect-types.h | 4 + .../src/lib/include/uapi/asm/infect-types.h | 5 ++ .../src/lib/include/uapi/asm/infect-types.h | 5 ++ .../src/lib/include/uapi/asm/infect-types.h | 23 +++++ compel/arch/x86/src/lib/thread_area.c | 88 +++++++++++++++++++ compel/include/infect-priv.h | 3 + compel/src/lib/infect.c | 5 ++ criu/arch/arm/include/asm/parasite.h | 1 + criu/arch/x86/include/asm/parasite.h | 77 ++-------------- criu/arch/x86/include/asm/restorer.h | 1 + criu/arch/x86/include/asm/types.h | 13 --- criu/parasite-syscall.c | 10 +++ 15 files changed, 164 insertions(+), 85 deletions(-) create mode 100644 compel/arch/x86/src/lib/thread_area.c diff --git a/compel/Makefile b/compel/Makefile index de9318c42d..b79aee6871 100644 --- a/compel/Makefile +++ b/compel/Makefile @@ -28,6 +28,10 @@ lib-y += src/lib/infect-util.o lib-y += src/lib/infect.o lib-y += src/lib/ptrace.o +ifeq ($(ARCH),x86) +lib-y += arch/$(ARCH)/src/lib/thread_area.o +endif + # handle_elf() has no support of ELF relocations on ARM (yet?) ifneq ($(filter arm aarch64,$(ARCH)),) CFLAGS += -DNO_RELOCS diff --git a/compel/arch/aarch64/src/lib/include/uapi/asm/infect-types.h b/compel/arch/aarch64/src/lib/include/uapi/asm/infect-types.h index 7a33baa8ef..b52f7a766c 100644 --- a/compel/arch/aarch64/src/lib/include/uapi/asm/infect-types.h +++ b/compel/arch/aarch64/src/lib/include/uapi/asm/infect-types.h @@ -18,6 +18,11 @@ typedef struct user_pt_regs user_regs_struct_t; typedef struct user_fpsimd_state user_fpregs_struct_t; +#define __compel_arch_fetch_thread_area(tid, th) 0 +#define compel_arch_fetch_thread_area(tctl) 0 +#define compel_arch_get_tls_task(ctl, tls) +#define compel_arch_get_tls_thread(tctl, tls) + #define REG_RES(r) ((uint64_t)(r).regs[0]) #define REG_IP(r) ((uint64_t)(r).pc) #define REG_SP(r) ((uint64_t)((r).sp)) diff --git a/compel/arch/arm/src/lib/include/uapi/asm/infect-types.h b/compel/arch/arm/src/lib/include/uapi/asm/infect-types.h index 69222b251f..5e05ef53d4 100644 --- a/compel/arch/arm/src/lib/include/uapi/asm/infect-types.h +++ b/compel/arch/arm/src/lib/include/uapi/asm/infect-types.h @@ -17,6 +17,11 @@ typedef struct { long uregs[18]; } user_regs_struct_t; +#define __compel_arch_fetch_thread_area(tid, th) 0 +#define compel_arch_fetch_thread_area(tctl) 0 +#define compel_arch_get_tls_task(ctl, tls) +#define compel_arch_get_tls_thread(tctl, tls) + typedef struct user_vfp user_fpregs_struct_t; #define ARM_cpsr uregs[16] diff --git a/compel/arch/mips/src/lib/include/uapi/asm/infect-types.h b/compel/arch/mips/src/lib/include/uapi/asm/infect-types.h index 423880821e..07f3936a9c 100755 --- a/compel/arch/mips/src/lib/include/uapi/asm/infect-types.h +++ b/compel/arch/mips/src/lib/include/uapi/asm/infect-types.h @@ -54,6 +54,10 @@ static inline bool user_regs_native(user_regs_struct_t *pregs) return true; } +#define __compel_arch_fetch_thread_area(tid, th) 0 +#define compel_arch_fetch_thread_area(tctl) 0 +#define compel_arch_get_tls_task(ctl, tls) +#define compel_arch_get_tls_thread(tctl, tls) #define REG_RES(regs) ((regs).MIPS_v0) #define REG_IP(regs) ((regs).cp0_epc) diff --git a/compel/arch/ppc64/src/lib/include/uapi/asm/infect-types.h b/compel/arch/ppc64/src/lib/include/uapi/asm/infect-types.h index 126fa2ea31..b65c942ee7 100644 --- a/compel/arch/ppc64/src/lib/include/uapi/asm/infect-types.h +++ b/compel/arch/ppc64/src/lib/include/uapi/asm/infect-types.h @@ -83,4 +83,9 @@ typedef struct { #define __NR(syscall, compat) ({ (void)compat; __NR_##syscall; }) +#define __compel_arch_fetch_thread_area(tid, th) 0 +#define compel_arch_fetch_thread_area(tctl) 0 +#define compel_arch_get_tls_task(ctl, tls) +#define compel_arch_get_tls_thread(tctl, tls) + #endif /* UAPI_COMPEL_ASM_TYPES_H__ */ diff --git a/compel/arch/s390/src/lib/include/uapi/asm/infect-types.h b/compel/arch/s390/src/lib/include/uapi/asm/infect-types.h index 8171d33951..807be5a9a8 100644 --- a/compel/arch/s390/src/lib/include/uapi/asm/infect-types.h +++ b/compel/arch/s390/src/lib/include/uapi/asm/infect-types.h @@ -84,4 +84,9 @@ struct mmap_arg_struct { unsigned long offset; }; +#define __compel_arch_fetch_thread_area(tid, th) 0 +#define compel_arch_fetch_thread_area(tctl) 0 +#define compel_arch_get_tls_task(ctl, tls) +#define compel_arch_get_tls_thread(tctl, tls) + #endif /* UAPI_COMPEL_ASM_TYPES_H__ */ diff --git a/compel/arch/x86/src/lib/include/uapi/asm/infect-types.h b/compel/arch/x86/src/lib/include/uapi/asm/infect-types.h index e6d394989b..470a1b0fd2 100644 --- a/compel/arch/x86/src/lib/include/uapi/asm/infect-types.h +++ b/compel/arch/x86/src/lib/include/uapi/asm/infect-types.h @@ -9,6 +9,29 @@ #define SIGMAX 64 #define SIGMAX_OLD 31 +#define ARCH_HAS_PTRACE_GET_THREAD_AREA + +/* + * Linux preserves three TLS segments in GDT. + * Offsets in GDT differ between 32-bit and 64-bit machines. + * For 64-bit x86 those GDT offsets are the same + * for native and compat tasks. + */ +#define GDT_ENTRY_TLS_MIN 12 +#define GDT_ENTRY_TLS_MAX 14 +#define GDT_ENTRY_TLS_NUM 3 +typedef struct { + user_desc_t desc[GDT_ENTRY_TLS_NUM]; +} tls_t; + +struct thread_ctx; +struct parasite_ctl; +struct parasite_thread_ctl; +extern int __compel_arch_fetch_thread_area(int tid, struct thread_ctx *th); +extern int compel_arch_fetch_thread_area(struct parasite_thread_ctl *tctl); +extern void compel_arch_get_tls_thread(struct parasite_thread_ctl *tctl, tls_t *out); +extern void compel_arch_get_tls_task(struct parasite_ctl *ctl, tls_t *out); + typedef struct { uint64_t r15; uint64_t r14; diff --git a/compel/arch/x86/src/lib/thread_area.c b/compel/arch/x86/src/lib/thread_area.c new file mode 100644 index 0000000000..f581496a78 --- /dev/null +++ b/compel/arch/x86/src/lib/thread_area.c @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include "log.h" +#include "asm/infect-types.h" +#include "infect.h" +#include "infect-priv.h" + +#ifndef PTRACE_GET_THREAD_AREA +# define PTRACE_GET_THREAD_AREA 25 +#endif + +/* + * For 64-bit applications, TLS (fs_base for Glibc) is in MSR, + * which are dumped with the help of ptrace() and restored with + * arch_prctl(ARCH_SET_FS/ARCH_SET_GS). + * + * But SET_FS_BASE will update GDT if base pointer fits in 4 bytes. + * Otherwise it will set only MSR, which allows for mixed 64/32-bit + * code to use: 2 MSRs as TLS base _and_ 3 GDT entries. + * Having in sum 5 TLS pointers, 3 of which are four bytes and + * other two eight bytes: + * struct thread_struct { + * struct desc_struct tls_array[3]; + * ... + * #ifdef CONFIG_X86_64 + * unsigned long fsbase; + * unsigned long gsbase; + * #endif + * ... + * }; + * + * Most x86_64 applications don't use GDT, but mixed code (i.e. Wine) + * can use it. Be pessimistic and dump it for 64-bit applications too. + */ +int __compel_arch_fetch_thread_area(int tid, struct thread_ctx *th) +{ + bool native_mode = user_regs_native(&th->regs); + tls_t *ptls = &th->tls; + int err, i; + + /* Initialise as not present by default */ + for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) { + user_desc_t *d = &ptls->desc[i]; + + memset(d, 0, sizeof(user_desc_t)); + d->seg_not_present = 1; + d->entry_number = GDT_ENTRY_TLS_MIN + i; + } + + for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) + { + user_desc_t *d = &ptls->desc[i]; + + err = ptrace(PTRACE_GET_THREAD_AREA, tid, + GDT_ENTRY_TLS_MIN + i, d); + /* + * Ignoring absent syscall on !CONFIG_IA32_EMULATION + * where such mixed code can't run. + * XXX: Add compile CONFIG_X86_IGNORE_64BIT_TLS + * (for x86_64 systems with CONFIG_IA32_EMULATION) + */ + if (err == -EIO && native_mode) + return 0; + if (err) { + pr_perror("get_thread_area failed for %d\n", tid); + return err; + } + } + + return 0; +} + +int compel_arch_fetch_thread_area(struct parasite_thread_ctl *tctl) +{ + return __compel_arch_fetch_thread_area(tctl->tid, &tctl->th); +} + +void compel_arch_get_tls_task(struct parasite_ctl *ctl, tls_t *out) +{ + memcpy(out, &ctl->orig.tls, sizeof(tls_t)); +} + +void compel_arch_get_tls_thread(struct parasite_thread_ctl *tctl, tls_t *out) +{ + memcpy(out, &tctl->th.tls, sizeof(tls_t)); +} diff --git a/compel/include/infect-priv.h b/compel/include/infect-priv.h index 8e1f990d5e..308c027adb 100644 --- a/compel/include/infect-priv.h +++ b/compel/include/infect-priv.h @@ -8,6 +8,9 @@ struct thread_ctx { k_rtsigset_t sigmask; user_regs_struct_t regs; +#ifdef ARCH_HAS_PTRACE_GET_THREAD_AREA + tls_t tls; +#endif }; /* parasite control block */ diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 4f2402feeb..3a815393bb 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -681,6 +681,11 @@ static int parasite_start_daemon(struct parasite_ctl *ctl) return -1; } + if (__compel_arch_fetch_thread_area(pid, &ctl->orig)) { + pr_err("Can't get thread area of %d\n", pid); + return -1; + } + if (ictx->make_sigframe(ictx->regs_arg, ctl->sigframe, ctl->rsigframe, &ctl->orig.sigmask)) return -1; diff --git a/criu/arch/arm/include/asm/parasite.h b/criu/arch/arm/include/asm/parasite.h index 0ed320ba6b..7f1e219c6f 100644 --- a/criu/arch/arm/include/asm/parasite.h +++ b/criu/arch/arm/include/asm/parasite.h @@ -1,6 +1,7 @@ #ifndef __ASM_PARASITE_H__ #define __ASM_PARASITE_H__ +/* kuser_get_tls() kernel-provided user-helper, the address is emulated */ static inline void arch_get_tls(tls_t *ptls) { *ptls = ((tls_t (*)(void))0xffff0fe0)(); diff --git a/criu/arch/x86/include/asm/parasite.h b/criu/arch/x86/include/asm/parasite.h index 6b4d4ac59a..678fc75e22 100644 --- a/criu/arch/x86/include/asm/parasite.h +++ b/criu/arch/x86/include/asm/parasite.h @@ -1,77 +1,10 @@ #ifndef __ASM_PARASITE_H__ #define __ASM_PARASITE_H__ -#include -#include -#include "asm/compat.h" - -static int arch_get_user_desc(user_desc_t *desc) -{ - int ret = __NR32_get_thread_area; - /* - * For 64-bit applications, TLS (fs_base for Glibc) is - * in MSR, which are dumped with the help of arch_prctl(). - * - * But SET_FS_BASE will update GDT if base pointer fits in 4 bytes. - * Otherwise it will set only MSR, which allows for mixed 64/32-bit - * code to use: 2 MSRs as TLS base _and_ 3 GDT entries. - * Having in sum 5 TLS pointers, 3 of which are four bytes and - * other two bigger than four bytes: - * struct thread_struct { - * struct desc_struct tls_array[3]; - * ... - * #ifdef CONFIG_X86_64 - * unsigned long fsbase; - * unsigned long gsbase; - * #endif - * ... - * }; - */ - asm volatile ( - " mov %0,%%eax \n" - " mov %1,%%rbx \n" - " int $0x80 \n" - " mov %%eax,%0 \n" - : "+m"(ret) - : "m"(desc) - : "rax", "rbx", "r8", "r9", "r10", "r11", "memory"); - - if (ret) - pr_err("Failed to dump TLS descriptor #%d: %d\n", - desc->entry_number, ret); - return ret; -} - -static void arch_get_tls(tls_t *ptls) -{ - void *syscall_mem; - int i; - - syscall_mem = alloc_compat_syscall_stack(); - if (!syscall_mem) { - pr_err("Failed to allocate memory <4Gb for compat syscall\n"); - - for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) { - user_desc_t *d = &ptls->desc[i]; - - d->seg_not_present = 1; - d->entry_number = GDT_ENTRY_TLS_MIN + i; - } - return; - } - - for (i = 0; i < GDT_ENTRY_TLS_NUM; i++) - { - user_desc_t *d = syscall_mem; - - memset(d, 0, sizeof(user_desc_t)); - d->seg_not_present = 1; - d->entry_number = GDT_ENTRY_TLS_MIN + i; - arch_get_user_desc(d); - memcpy(&ptls->desc[i], d, sizeof(user_desc_t)); - } - - free_compat_syscall_stack(syscall_mem); -} +/* + * TLS is accessed through PTRACE_GET_THREAD_AREA, + * see compel_arch_fetch_thread_area(). + */ +static inline void arch_get_tls(tls_t *ptls) { (void)ptls; } #endif diff --git a/criu/arch/x86/include/asm/restorer.h b/criu/arch/x86/include/asm/restorer.h index 731477ec99..6ba0740206 100644 --- a/criu/arch/x86/include/asm/restorer.h +++ b/criu/arch/x86/include/asm/restorer.h @@ -3,6 +3,7 @@ #include "asm/types.h" #include +#include #include "images/core.pb-c.h" #include #include diff --git a/criu/arch/x86/include/asm/types.h b/criu/arch/x86/include/asm/types.h index 3ff7fc630a..012358949b 100644 --- a/criu/arch/x86/include/asm/types.h +++ b/criu/arch/x86/include/asm/types.h @@ -36,17 +36,4 @@ static inline void *decode_pointer(u64 v) { return (void*)(long)v; } #define AT_VECTOR_SIZE 44 typedef uint64_t auxv_t; -/* - * Linux preserves three TLS segments in GDT. - * Offsets in GDT differ between 32-bit and 64-bit machines. - * For 64-bit x86 those GDT offsets are the same - * for native and compat tasks. - */ -#define GDT_ENTRY_TLS_MIN 12 -#define GDT_ENTRY_TLS_MAX 14 -#define GDT_ENTRY_TLS_NUM 3 -typedef struct { - user_desc_t desc[GDT_ENTRY_TLS_NUM]; -} tls_t; - #endif /* __CR_ASM_TYPES_H__ */ diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c index c7074c7c46..a961cb8ae4 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -156,6 +156,8 @@ int parasite_dump_thread_leader_seized(struct parasite_ctl *ctl, int pid, CoreEn return -1; } + compel_arch_get_tls_task(ctl, &args->tls); + return dump_thread_core(pid, core, args); } @@ -190,6 +192,14 @@ int parasite_dump_thread_seized(struct parasite_thread_ctl *tctl, goto err_rth; } + ret = compel_arch_fetch_thread_area(tctl); + if (ret) { + pr_err("Can't obtain thread area of %d\n", pid); + goto err_rth; + } + + compel_arch_get_tls_thread(tctl, &args->tls); + ret = compel_run_in_thread(tctl, PARASITE_CMD_DUMP_THREAD); if (ret) { pr_err("Can't init thread in parasite %d\n", pid); From e4e58a8f38edabf81a76b8fbfae395fc4b3819cf Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Thu, 25 Feb 2021 12:56:37 +0300 Subject: [PATCH 127/204] namespaces: properly handle errors of snprintf If snprintf was truncated we should probably know about it instead of continuing to increase off, as snprintf returns number of characters which would have been written and not the number which was actually written. Normally we check snprintf only for overflow not for error, some modern compilers print warnings if truncation was not checked. Probably it was the case why we implemented [1], the truncation happened and on the next iteration of for loop we've hit negative size for snprintf and got -1. Fixes: 90f043dea ("namespaces: handle errors of snprintf") [1] Signed-off-by: Pavel Tikhomirov --- criu/namespaces.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/criu/namespaces.c b/criu/namespaces.c index ccd6e1323f..aecc82f66e 100644 --- a/criu/namespaces.c +++ b/criu/namespaces.c @@ -1173,6 +1173,9 @@ static int write_id_map(pid_t pid, UidGidExtent **extents, int n, char *id_map) if (len < 0) { pr_perror("Unable to form the user/group mappings buffer"); return -1; + } else if (len >= sizeof(buf) - off) { + pr_err("The user/group mappings buffer truncated\n"); + return -1; } off += len; } From 2fdc09499d9df9c9e61d53cf0c121e3338538a8f Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 25 Feb 2021 19:57:10 +0000 Subject: [PATCH 128/204] x86/compel/fault-inject: Add a fault-injection for corrupting extended regset With pseudo-random garbage, the seed is printed with pr_err(). get_task_regs() is called during seizing the task and also for each thread. At this moment only for x86. Signed-off-by: Dmitry Safonov --- compel/arch/x86/src/lib/cpu.c | 2 +- .../arch/x86/src/lib/include/uapi/asm/fpu.h | 4 +- compel/arch/x86/src/lib/infect.c | 79 +++++++++++++++++++ compel/include/uapi/infect.h | 2 + criu/include/fault-injection.h | 1 + criu/parasite-syscall.c | 2 + 6 files changed, 87 insertions(+), 3 deletions(-) diff --git a/compel/arch/x86/src/lib/cpu.c b/compel/arch/x86/src/lib/cpu.c index 6175121673..c96f013534 100644 --- a/compel/arch/x86/src/lib/cpu.c +++ b/compel/arch/x86/src/lib/cpu.c @@ -125,7 +125,7 @@ static int compel_fpuid(compel_cpuinfo_t *c) c->xfeatures_mask &= ~(1 << i); } - c->xfeatures_mask &= XCNTXT_MASK; + c->xfeatures_mask &= XFEATURE_MASK_USER; c->xfeatures_mask &= ~XFEATURE_MASK_SUPERVISOR; /* diff --git a/compel/arch/x86/src/lib/include/uapi/asm/fpu.h b/compel/arch/x86/src/lib/include/uapi/asm/fpu.h index 4ff531fb9c..8985ad7f62 100644 --- a/compel/arch/x86/src/lib/include/uapi/asm/fpu.h +++ b/compel/arch/x86/src/lib/include/uapi/asm/fpu.h @@ -76,7 +76,7 @@ enum xfeature { #define XFEATURE_MASK_SUPERVISOR (XFEATURE_MASK_PT | XFEATURE_HDC) /* All currently supported features */ -#define XCNTXT_MASK \ +#define XFEATURE_MASK_USER \ (XFEATURE_MASK_FP | XFEATURE_MASK_SSE | \ XFEATURE_MASK_YMM | XFEATURE_MASK_OPMASK | \ XFEATURE_MASK_ZMM_Hi256 | XFEATURE_MASK_Hi16_ZMM | \ @@ -232,7 +232,7 @@ struct pkru_state { * can vary quite a bit between CPUs. * * - * One page should be enough for the whole xsave state. + * One page should be enough for the whole xsave state ;-) */ #define EXTENDED_STATE_AREA_SIZE (4096 - sizeof(struct i387_fxsave_struct) - sizeof(struct xsave_hdr_struct)) diff --git a/compel/arch/x86/src/lib/infect.c b/compel/arch/x86/src/lib/infect.c index 9c4abb60c2..4010019426 100644 --- a/compel/arch/x86/src/lib/infect.c +++ b/compel/arch/x86/src/lib/infect.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include @@ -258,6 +260,80 @@ static int get_task_fpregs(pid_t pid, user_fpregs_struct_t *xsave) return 0; } +/* See arch/x86/kernel/fpu/xstate.c */ +static void validate_random_xstate(struct xsave_struct *xsave) +{ + struct xsave_hdr_struct *hdr = &xsave->xsave_hdr; + unsigned int i; + + /* No unknown or supervisor features may be set */ + hdr->xstate_bv &= XFEATURE_MASK_USER; + hdr->xstate_bv &= ~XFEATURE_MASK_SUPERVISOR; + + for (i = 0; i < XFEATURE_MAX; i++) { + if (!compel_fpu_has_feature(i)) + hdr->xstate_bv &= ~(1 << i); + } + + /* Userspace must use the uncompacted format */ + hdr->xcomp_bv = 0; + + /* + * If 'reserved' is shrunken to add a new field, make sure to validate + * that new field here! + */ + BUILD_BUG_ON(sizeof(hdr->reserved) != 48); + + /* No reserved bits may be set */ + memset(&hdr->reserved, 0, sizeof(hdr->reserved)); +} + +/* + * TODO: Put fault-injection under CONFIG_* and move + * extended regset corruption to generic code + */ +static int corrupt_extregs(pid_t pid) +{ + bool use_xsave = compel_cpu_has_feature(X86_FEATURE_OSXSAVE); + user_fpregs_struct_t ext_regs; + int *rand_to = (int *)&ext_regs; + unsigned int seed; + size_t i; + + seed = time(NULL); + for (i = 0; i < sizeof(ext_regs) / sizeof(int); i++) + *rand_to++ = rand_r(&seed); + + /* + * Error log-level as: + * - not intended to be used outside of testing, + * - zdtm.py will grep it auto-magically from logs + * (and the seed will be known from an automatical testing) + */ + pr_err("Corrupting %s for %d, seed %u\n", + use_xsave ? "xsave" : "fpuregs", pid, seed); + + if (!use_xsave) { + if (ptrace(PTRACE_SETFPREGS, pid, NULL, &ext_regs)) { + pr_perror("Can't set FPU registers for %d", pid); + return -1; + } + } else { + struct iovec iov; + + validate_random_xstate((void *)&ext_regs); + + iov.iov_base = &ext_regs; + iov.iov_len = sizeof(ext_regs); + + if (ptrace(PTRACE_SETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) { + pr_perror("Can't set xstate for %d", pid); + return -1; + } + } + return 0; +} + int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, void *arg, unsigned long flags) { @@ -309,6 +385,9 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, ret = get_task_xsave(pid, &xsave); } + if (!ret && unlikely(flags & INFECT_CORRUPT_EXTREGS)) + ret = corrupt_extregs(pid); + if (ret) goto err; diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h index fa326eafec..6cf3daf467 100644 --- a/compel/include/uapi/infect.h +++ b/compel/include/uapi/infect.h @@ -136,6 +136,8 @@ extern struct infect_ctx *compel_infect_ctx(struct parasite_ctl *); #define INFECT_COMPATIBLE (1UL << 3) /* Workaround for ptrace bug on Skylake CPUs with kernels older than v4.14 */ #define INFECT_X86_PTRACE_MXCSR_BUG (1UL << 4) +/* After infecting - corrupt extended registers (fault-injection) */ +#define INFECT_CORRUPT_EXTREGS (1UL << 5) /* * There are several ways to describe a blob to compel diff --git a/criu/include/fault-injection.h b/criu/include/fault-injection.h index 31fe161784..0fd9b512d9 100644 --- a/criu/include/fault-injection.h +++ b/criu/include/fault-injection.h @@ -18,6 +18,7 @@ enum faults { FI_PARTIAL_PAGES = 131, FI_HUGE_ANON_SHMEM_ID = 132, FI_CANNOT_MAP_VDSO = 133, + FI_CORRUPT_EXTREGS = 134, FI_MAX, }; diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c index a961cb8ae4..04364e5bf1 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -575,6 +575,8 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ictx->flags |= INFECT_COMPATIBLE; if (kdat.x86_has_ptrace_fpu_xsave_bug) ictx->flags |= INFECT_X86_PTRACE_MXCSR_BUG; + if (fault_injected(FI_CORRUPT_EXTREGS)) + ictx->flags |= INFECT_CORRUPT_EXTREGS; ictx->log_fd = log_get_fd(); From 6e1cd5b6a7bcb58c75421fb3c7d62e5dcb314d42 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 25 Feb 2021 23:10:49 +0000 Subject: [PATCH 129/204] zdtm/fpu00: Simplify ifdeffery ..to introduce a new one! ;-D Signed-off-by: Dmitry Safonov --- test/zdtm/static/fpu00.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/test/zdtm/static/fpu00.c b/test/zdtm/static/fpu00.c index 04aa738fdf..e9fcb7e18e 100644 --- a/test/zdtm/static/fpu00.c +++ b/test/zdtm/static/fpu00.c @@ -44,17 +44,14 @@ int chk_proc_fpu(void) return edx & CPUID_FEAT_EDX_FPU; } -#endif int main(int argc, char ** argv) { -#if defined(__i386__) || defined(__x86_64__) float a, b, c, d; float res1, res2; -#endif test_init(argc, argv); -#if defined(__i386__) || defined(__x86_64__) + if (!chk_proc_fpu()) { skip("FPU not supported"); return 1; @@ -80,8 +77,17 @@ int main(int argc, char ** argv) fail("%f != %f\n", res1, res2); else pass(); + + return 0; +} + #else + +int main(int argc, char *argv[]) +{ + test_init(argc, argv); skip("Unsupported arch"); -#endif return 0; } + +#endif From 8394062e46e7fee371be3538f22c87353c39c24d Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Thu, 25 Feb 2021 23:35:15 +0000 Subject: [PATCH 130/204] zdtm/fpu03: Add a test to check fpu C/R in a thread CRIU dumps main thread and sub-threads differently, so there needed a test to check if fpu is preserved across C/R in sub-threads. Signed-off-by: Dmitry Safonov --- test/zdtm/static/Makefile | 3 +++ test/zdtm/static/fpu00.c | 45 +++++++++++++++++++++++++++++++-------- test/zdtm/static/fpu03.c | 1 + 3 files changed, 40 insertions(+), 9 deletions(-) create mode 120000 test/zdtm/static/fpu03.c diff --git a/test/zdtm/static/Makefile b/test/zdtm/static/Makefile index d0974bb0dd..53dee92c5c 100644 --- a/test/zdtm/static/Makefile +++ b/test/zdtm/static/Makefile @@ -14,6 +14,7 @@ TST_NOFILE := \ fpu00 \ fpu01 \ fpu02 \ + fpu03 \ arm-neon00 \ futex \ futex-rl \ @@ -496,6 +497,8 @@ $(TST): | $(LIB) aio00: LDLIBS += -laio different_creds: LDLIBS += -lcap file_locks06 file_locks07 file_locks08: ofd_file_locks.o +fpu03: CFLAGS += -pthread -D ZDTM_FPU00_RUN_IN_THREAD +fpu03: LDFLAGS += -pthread futex: CFLAGS += -pthread futex: LDFLAGS += -pthread futex-rl: CFLAGS += -pthread diff --git a/test/zdtm/static/fpu00.c b/test/zdtm/static/fpu00.c index e9fcb7e18e..6f2e1c2bf7 100644 --- a/test/zdtm/static/fpu00.c +++ b/test/zdtm/static/fpu00.c @@ -1,4 +1,5 @@ #include +#include #include "zdtmtst.h" @@ -45,18 +46,11 @@ int chk_proc_fpu(void) return edx & CPUID_FEAT_EDX_FPU; } -int main(int argc, char ** argv) +void *run_fpu_test(void *unused) { float a, b, c, d; float res1, res2; - test_init(argc, argv); - - if (!chk_proc_fpu()) { - skip("FPU not supported"); - return 1; - } - a = drand48(); b = drand48(); c = drand48(); @@ -78,7 +72,40 @@ int main(int argc, char ** argv) else pass(); - return 0; + return (void *)(uintptr_t)(res1 != res2); +} + +int main(int argc, char ** argv) +{ + test_init(argc, argv); + + if (!chk_proc_fpu()) { + skip("FPU not supported"); + return 1; + } + + +#ifdef ZDTM_FPU00_RUN_IN_THREAD + /* Check if thread's fpu state is preserved */ + { + pthread_t child; + void *ret; + + if (pthread_create(&child, NULL, &run_fpu_test, NULL)) { + pr_perror("Can't create pthread\n"); + exit(1); + } + + if (pthread_join(child, &ret)) { + pr_perror("Can't join pthread\n"); + exit(1); + } + + exit(!!ret); + } +#else + return !!run_fpu_test(NULL); +#endif } #else diff --git a/test/zdtm/static/fpu03.c b/test/zdtm/static/fpu03.c new file mode 120000 index 0000000000..158732c022 --- /dev/null +++ b/test/zdtm/static/fpu03.c @@ -0,0 +1 @@ +fpu00.c \ No newline at end of file From e9b1e0b74cd94f7071be9f9b4636d2ebc556cfce Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 26 Feb 2021 01:08:00 +0000 Subject: [PATCH 131/204] compel: Store extended registers set in the thread context Extended registers set for task is restored with rt_sigreturn() through prepared sigframe. For threads it's currently lost. Preserve it inside thread context to restore on thread curing. Signed-off-by: Dmitry Safonov --- compel/arch/aarch64/src/lib/infect.c | 11 ++++++----- compel/arch/arm/src/lib/infect.c | 9 +++++---- compel/arch/mips/src/lib/infect.c | 8 ++++---- compel/arch/ppc64/src/lib/infect.c | 9 +++++---- compel/arch/s390/src/lib/infect.c | 25 +++++++++++++------------ compel/arch/x86/src/lib/infect.c | 14 +++++++------- compel/include/infect-priv.h | 12 +++++++++++- compel/src/lib/infect.c | 7 ++++--- 8 files changed, 55 insertions(+), 40 deletions(-) diff --git a/compel/arch/aarch64/src/lib/infect.c b/compel/arch/aarch64/src/lib/infect.c index 4b5939022c..39428cd8da 100644 --- a/compel/arch/aarch64/src/lib/infect.c +++ b/compel/arch/aarch64/src/lib/infect.c @@ -60,11 +60,12 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, return 0; } -int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, __maybe_unused unsigned long flags) { + user_fpregs_struct_t tmp, *fpsimd = ext_regs ? ext_regs : &tmp; struct iovec iov; - user_fpregs_struct_t fpsimd; int ret; pr_info("Dumping GP/FPU registers for %d\n", pid); @@ -76,14 +77,14 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, goto err; } - iov.iov_base = &fpsimd; - iov.iov_len = sizeof(fpsimd); + iov.iov_base = fpsimd; + iov.iov_len = sizeof(*fpsimd); if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov))) { pr_perror("Failed to obtain FPU registers for %d", pid); goto err; } - ret = save(arg, regs, &fpsimd); + ret = save(arg, regs, fpsimd); err: return ret; } diff --git a/compel/arch/arm/src/lib/infect.c b/compel/arch/arm/src/lib/infect.c index 75b985b74b..dd5aa97845 100644 --- a/compel/arch/arm/src/lib/infect.c +++ b/compel/arch/arm/src/lib/infect.c @@ -69,15 +69,16 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, } #define PTRACE_GETVFPREGS 27 -int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, __maybe_unused unsigned long flags) { - user_fpregs_struct_t vfp; + user_fpregs_struct_t tmp, *vfp = ext_regs ? ext_regs : &tmp; int ret = -1; pr_info("Dumping GP/FPU registers for %d\n", pid); - if (ptrace(PTRACE_GETVFPREGS, pid, NULL, &vfp)) { + if (ptrace(PTRACE_GETVFPREGS, pid, NULL, vfp)) { pr_perror("Can't obtain FPU registers for %d", pid); goto err; } @@ -99,7 +100,7 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, } } - ret = save(arg, regs, &vfp); + ret = save(arg, regs, vfp); err: return ret; } diff --git a/compel/arch/mips/src/lib/infect.c b/compel/arch/mips/src/lib/infect.c index 35e947cc0e..6a53b3c3bf 100755 --- a/compel/arch/mips/src/lib/infect.c +++ b/compel/arch/mips/src/lib/infect.c @@ -122,13 +122,14 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, return 0; } -int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, __maybe_unused unsigned long flags) { - user_fpregs_struct_t xsave = { }, *xs = NULL; + user_fpregs_struct_t xsave = { }, *xs = ext_regs ? ext_regs : &xsave; int ret = -1; - if (ptrace(PTRACE_GETFPREGS, pid, NULL, &xsave)) { + if (ptrace(PTRACE_GETFPREGS, pid, NULL, xs)) { pr_perror("Can't obtain FPU registers for %d", pid); return ret; } @@ -151,7 +152,6 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, regs->regs[0] = 0; } - xs = &xsave; ret = save(arg, regs, xs); return ret; } diff --git a/compel/arch/ppc64/src/lib/infect.c b/compel/arch/ppc64/src/lib/infect.c index b2c725f62f..339e012091 100644 --- a/compel/arch/ppc64/src/lib/infect.c +++ b/compel/arch/ppc64/src/lib/infect.c @@ -372,17 +372,18 @@ static int __get_task_regs(pid_t pid, user_regs_struct_t *regs, return 0; } -int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, __maybe_unused unsigned long flags) { - user_fpregs_struct_t fpregs; + user_fpregs_struct_t tmp, *fpregs = ext_regs ? ext_regs : &tmp; int ret; - ret = __get_task_regs(pid, regs, &fpregs); + ret = __get_task_regs(pid, regs, fpregs); if (ret) return ret; - return save(arg, regs, &fpregs); + return save(arg, regs, fpregs); } int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, diff --git a/compel/arch/s390/src/lib/infect.c b/compel/arch/s390/src/lib/infect.c index 5a4675449d..5b3c0d62e6 100644 --- a/compel/arch/s390/src/lib/infect.c +++ b/compel/arch/s390/src/lib/infect.c @@ -310,31 +310,32 @@ static int s390_disable_ri_bit(pid_t pid, user_regs_struct_t *regs) /* * Prepare task registers for restart */ -int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, __maybe_unused unsigned long flags) { - user_fpregs_struct_t fpregs; + user_fpregs_struct_t tmp, *fpregs = ext_regs ? ext_regs : &tmp; struct iovec iov; int rewind; - print_user_regs_struct("get_task_regs", pid, regs); + print_user_regs_struct("compel_get_task_regs", pid, regs); - memset(&fpregs, 0, sizeof(fpregs)); - iov.iov_base = &fpregs.prfpreg; - iov.iov_len = sizeof(fpregs.prfpreg); + memset(fpregs, 0, sizeof(*fpregs)); + iov.iov_base = &fpregs->prfpreg; + iov.iov_len = sizeof(fpregs->prfpreg); if (ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov) < 0) { pr_perror("Couldn't get floating-point registers"); return -1; } - if (get_vx_regs(pid, &fpregs)) { + if (get_vx_regs(pid, fpregs)) { pr_perror("Couldn't get vector registers"); return -1; } - if (get_gs_cb(pid, &fpregs)) { + if (get_gs_cb(pid, fpregs)) { pr_perror("Couldn't get guarded-storage"); return -1; } - if (get_ri_cb(pid, &fpregs)) { + if (get_ri_cb(pid, fpregs)) { pr_perror("Couldn't get runtime-instrumentation"); return -1; } @@ -343,10 +344,10 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, * before we execute parasite code. Otherwise parasite operations * would be recorded. */ - if (fpregs.flags & USER_RI_ON) + if (fpregs->flags & USER_RI_ON) s390_disable_ri_bit(pid, regs); - print_user_fpregs_struct("get_task_regs", pid, &fpregs); + print_user_fpregs_struct("compel_get_task_regs", pid, fpregs); /* Check for system call restarting. */ if (regs->system_call) { rewind = regs->system_call >> 16; @@ -366,7 +367,7 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, } } /* Call save_task_regs() */ - return save(arg, regs, &fpregs); + return save(arg, regs, fpregs); } /* diff --git a/compel/arch/x86/src/lib/infect.c b/compel/arch/x86/src/lib/infect.c index 4010019426..9d81083f71 100644 --- a/compel/arch/x86/src/lib/infect.c +++ b/compel/arch/x86/src/lib/infect.c @@ -334,10 +334,11 @@ static int corrupt_extregs(pid_t pid) return 0; } -int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, unsigned long flags) { - user_fpregs_struct_t xsave = { }, *xs = NULL; + user_fpregs_struct_t xsave = { }, *xs = ext_regs ? ext_regs : &xsave; int ret = -1; pr_info("Dumping general registers for %d in %s mode\n", pid, @@ -371,18 +372,18 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, pr_info("Dumping GP/FPU registers for %d\n", pid); if (!compel_cpu_has_feature(X86_FEATURE_OSXSAVE)) { - ret = get_task_fpregs(pid, &xsave); + ret = get_task_fpregs(pid, xs); } else if (unlikely(flags & INFECT_X86_PTRACE_MXCSR_BUG)) { /* * get_task_fpregs() will fill FP state, * get_task_xsave() will overwrite rightly sse/mmx/etc */ pr_warn("Skylake xsave fpu bug workaround used\n"); - ret = get_task_fpregs(pid, &xsave); + ret = get_task_fpregs(pid, xs); if (!ret) - ret = get_task_xsave(pid, &xsave); + ret = get_task_xsave(pid, xs); } else { - ret = get_task_xsave(pid, &xsave); + ret = get_task_xsave(pid, xs); } if (!ret && unlikely(flags & INFECT_CORRUPT_EXTREGS)) @@ -391,7 +392,6 @@ int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, if (ret) goto err; - xs = &xsave; out: ret = save(arg, regs, xs); err: diff --git a/compel/include/infect-priv.h b/compel/include/infect-priv.h index 308c027adb..16114164c9 100644 --- a/compel/include/infect-priv.h +++ b/compel/include/infect-priv.h @@ -11,6 +11,7 @@ struct thread_ctx { #ifdef ARCH_HAS_PTRACE_GET_THREAD_AREA tls_t tls; #endif + user_fpregs_struct_t ext_regs; }; /* parasite control block */ @@ -61,7 +62,16 @@ extern void *remote_mmap(struct parasite_ctl *ctl, void *addr, size_t length, int prot, int flags, int fd, off_t offset); extern bool arch_can_dump_task(struct parasite_ctl *ctl); -extern int get_task_regs(pid_t pid, user_regs_struct_t *regs, save_regs_t save, +/* + * @regs: general purpose registers + * @ext_regs: extended register set (fpu/mmx/sse/etc) + * for task that is NULL, restored by sigframe on rt_sigreturn() + * @save: callback to dump all info + * @flags: see INFECT_* in infect_ctx::flags + * @pid: mystery + */ +extern int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, + user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, unsigned long flags); extern int arch_fetch_sas(struct parasite_ctl *ctl, struct rt_sigframe *s); extern int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 3a815393bb..d50356f6c4 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -671,11 +671,11 @@ static int parasite_start_daemon(struct parasite_ctl *ctl) /* * Get task registers before going daemon, since the - * compel_get_task_regs needs to call ptrace on _stopped_ task, + * compel_get_task_regs() needs to call ptrace on _stopped_ task, * while in daemon it is not such. */ - if (get_task_regs(pid, &ctl->orig.regs, ictx->save_regs, + if (compel_get_task_regs(pid, &ctl->orig.regs, NULL, ictx->save_regs, ictx->regs_arg, ictx->flags)) { pr_err("Can't obtain regs for thread %d\n", pid); return -1; @@ -1674,7 +1674,8 @@ k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl) int compel_get_thread_regs(struct parasite_thread_ctl *tctl, save_regs_t save, void * arg) { - return get_task_regs(tctl->tid, &tctl->th.regs, save, arg, tctl->ctl->ictx.flags); + return compel_get_task_regs(tctl->tid, &tctl->th.regs, &tctl->th.ext_regs, + save, arg, tctl->ctl->ictx.flags); } struct infect_ctx *compel_infect_ctx(struct parasite_ctl *ctl) From e07e5eee3c70dfee97ee296647dddb6c41eccacd Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 26 Feb 2021 02:25:57 +0000 Subject: [PATCH 132/204] compel: Provide compel_set_task_ext_regs() Arch-dependend way to restore extended registers set. Use it straight-away to restore per-thread registers. Signed-off-by: Dmitry Safonov --- compel/arch/aarch64/src/lib/infect.c | 15 ++++++++ compel/arch/arm/src/lib/infect.c | 11 ++++++ compel/arch/mips/src/lib/infect.c | 13 +++++++ compel/arch/ppc64/src/lib/infect.c | 28 ++++++++++++++ compel/arch/s390/src/lib/infect.c | 55 ++++++++++++++++++++++++++++ compel/arch/x86/src/lib/infect.c | 25 +++++++++++++ compel/include/infect-priv.h | 1 + compel/src/lib/infect.c | 25 +++++++++---- 8 files changed, 165 insertions(+), 8 deletions(-) diff --git a/compel/arch/aarch64/src/lib/infect.c b/compel/arch/aarch64/src/lib/infect.c index 39428cd8da..586eedac04 100644 --- a/compel/arch/aarch64/src/lib/infect.c +++ b/compel/arch/aarch64/src/lib/infect.c @@ -89,6 +89,21 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, return ret; } +int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs) +{ + struct iovec iov; + + pr_info("Restoring GP/FPU registers for %d\n", pid); + + iov.iov_base = ext_regs; + iov.iov_len = sizeof(*ext_regs); + if (ptrace(PTRACE_SETREGSET, pid, NT_PRFPREG, &iov)) { + pr_perror("Failed to set FPU registers for %d", pid); + return -1; + } + return 0; +} + int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, unsigned long arg1, unsigned long arg2, diff --git a/compel/arch/arm/src/lib/infect.c b/compel/arch/arm/src/lib/infect.c index dd5aa97845..1ddb486541 100644 --- a/compel/arch/arm/src/lib/infect.c +++ b/compel/arch/arm/src/lib/infect.c @@ -105,6 +105,17 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, return ret; } +int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs) +{ + pr_info("Restoring GP/FPU registers for %d\n", pid); + + if (ptrace(PTRACE_SETVFPREGS, pid, NULL, ext_regs)) { + pr_perror("Can't set FPU registers for %d", pid); + return -1; + } + return 0; +} + int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, unsigned long arg1, unsigned long arg2, diff --git a/compel/arch/mips/src/lib/infect.c b/compel/arch/mips/src/lib/infect.c index 6a53b3c3bf..0c8067f88b 100755 --- a/compel/arch/mips/src/lib/infect.c +++ b/compel/arch/mips/src/lib/infect.c @@ -129,6 +129,8 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t xsave = { }, *xs = ext_regs ? ext_regs : &xsave; int ret = -1; + pr_info("Dumping GP/FPU registers for %d\n", pid); + if (ptrace(PTRACE_GETFPREGS, pid, NULL, xs)) { pr_perror("Can't obtain FPU registers for %d", pid); return ret; @@ -156,6 +158,17 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, return ret; } +int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs) +{ + pr_info("Restoring GP/FPU registers for %d\n", pid); + + if (ptrace(PTRACE_SETFPREGS, pid, NULL, ext_regs)) { + pr_perror("Can't set FPU registers for %d", pid); + return -1; + } + return 0; +} + int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, unsigned long arg1, unsigned long arg2, diff --git a/compel/arch/ppc64/src/lib/infect.c b/compel/arch/ppc64/src/lib/infect.c index 339e012091..5797fb16d6 100644 --- a/compel/arch/ppc64/src/lib/infect.c +++ b/compel/arch/ppc64/src/lib/infect.c @@ -386,6 +386,34 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, return save(arg, regs, fpregs); } +int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs) +{ + int ret = 0; + + pr_info("Restoring GP/FPU registers for %d\n", pid); + + /* XXX: should restore TM registers somehow? */ + if (ext_regs->flags & USER_FPREGS_FL_FP) { + if (ptrace(PTRACE_SETFPREGS, pid, 0, (void *)&ext_regs->fpregs) < 0) { + pr_perror("Couldn't set floating-point registers"); + ret = -1; + } + } + + if (ext_regs->flags & USER_FPREGS_FL_ALTIVEC) { + if (ptrace(PTRACE_SETVRREGS, pid, 0, (void*)&ext_regs->vrregs) < 0) { + pr_perror("Couldn't set Altivec registers"); + ret = -1; + } + if (ptrace(PTRACE_SETVSRREGS, pid, 0, (void*)ext_regs->vsxregs) < 0) { + pr_perror("Couldn't set VSX registers"); + ret = -1; + } + } + + return ret; +} + int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, unsigned long arg1, unsigned long arg2, diff --git a/compel/arch/s390/src/lib/infect.c b/compel/arch/s390/src/lib/infect.c index 5b3c0d62e6..557b21203e 100644 --- a/compel/arch/s390/src/lib/infect.c +++ b/compel/arch/s390/src/lib/infect.c @@ -370,6 +370,61 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, return save(arg, regs, fpregs); } +int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs) +{ + struct iovec iov; + int ret = 0; + + iov.iov_base = &ext_regs->prfpreg; + iov.iov_len = sizeof(ext_regs->prfpreg); + if (ptrace(PTRACE_SETREGSET, pid, NT_PRFPREG, &iov) < 0) { + pr_perror("Couldn't set floating-point registers"); + ret = -1; + } + + if (ext_regs->flags & USER_FPREGS_VXRS) { + iov.iov_base = &ext_regs->vxrs_low; + iov.iov_len = sizeof(ext_regs->vxrs_low); + if (ptrace(PTRACE_SETREGSET, pid, NT_S390_VXRS_LOW, &iov) < 0) { + pr_perror("Couldn't set VXRS_LOW\n"); + ret = -1; + } + + iov.iov_base = &ext_regs->vxrs_high; + iov.iov_len = sizeof(ext_regs->vxrs_high); + if (ptrace(PTRACE_SETREGSET, pid, NT_S390_VXRS_HIGH, &iov) < 0) { + pr_perror("Couldn't set VXRS_HIGH\n"); + ret = -1; + } + } + + if (ext_regs->flags & USER_GS_CB) { + iov.iov_base = &ext_regs->gs_cb; + iov.iov_len = sizeof(ext_regs->gs_cb); + if (ptrace(PTRACE_SETREGSET, pid, NT_S390_GS_CB, &iov) < 0) { + pr_perror("Couldn't set GS_CB\n"); + ret = -1; + } + iov.iov_base = &ext_regs->gs_bc; + iov.iov_len = sizeof(ext_regs->gs_bc); + if (ptrace(PTRACE_SETREGSET, pid, NT_S390_GS_BC, &iov) < 0) { + pr_perror("Couldn't set GS_BC\n"); + ret = -1; + } + } + + if (ext_regs->flags & USER_RI_CB) { + iov.iov_base = &ext_regs->ri_cb; + iov.iov_len = sizeof(ext_regs->ri_cb); + if (ptrace(PTRACE_SETREGSET, pid, NT_S390_RI_CB, &iov) < 0) { + pr_perror("Couldn't set RI_CB\n"); + ret = -1; + } + } + + return ret; +} + /* * Injected syscall instruction */ diff --git a/compel/arch/x86/src/lib/infect.c b/compel/arch/x86/src/lib/infect.c index 9d81083f71..566238d2d2 100644 --- a/compel/arch/x86/src/lib/infect.c +++ b/compel/arch/x86/src/lib/infect.c @@ -398,6 +398,31 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, return ret; } +int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs) +{ + struct iovec iov; + + pr_info("Restoring GP/FPU registers for %d\n", pid); + + if (!compel_cpu_has_feature(X86_FEATURE_OSXSAVE)) { + if (ptrace(PTRACE_SETFPREGS, pid, NULL, ext_regs)) { + pr_perror("Can't set FPU registers for %d", pid); + return -1; + } + return 0; + } + + iov.iov_base = ext_regs; + iov.iov_len = sizeof(*ext_regs); + + if (ptrace(PTRACE_SETREGSET, pid, (unsigned int)NT_X86_XSTATE, &iov) < 0) { + pr_perror("Can't set FPU registers for %d", pid); + return -1; + } + + return 0; +} + int compel_syscall(struct parasite_ctl *ctl, int nr, long *ret, unsigned long arg1, unsigned long arg2, diff --git a/compel/include/infect-priv.h b/compel/include/infect-priv.h index 16114164c9..d4f19307d3 100644 --- a/compel/include/infect-priv.h +++ b/compel/include/infect-priv.h @@ -73,6 +73,7 @@ extern bool arch_can_dump_task(struct parasite_ctl *ctl); extern int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save, void *arg, unsigned long flags); +extern int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs); extern int arch_fetch_sas(struct parasite_ctl *ctl, struct rt_sigframe *s); extern int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs, diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index d50356f6c4..1bb07ace54 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -475,7 +475,8 @@ static int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack, return -1; } -static int restore_thread_ctx(int pid, struct thread_ctx *ctx) +static int restore_thread_ctx(int pid, struct thread_ctx *ctx, + bool restore_ext_regs) { int ret = 0; @@ -483,6 +484,10 @@ static int restore_thread_ctx(int pid, struct thread_ctx *ctx) pr_perror("Can't restore registers (pid: %d)", pid); ret = -1; } + + if (restore_ext_regs && compel_set_task_ext_regs(pid, &ctx->ext_regs)) + ret = -1; + if (ptrace(PTRACE_SETSIGMASK, pid, sizeof(k_rtsigset_t), &ctx->sigmask)) { pr_perror("Can't block signals"); ret = -1; @@ -491,11 +496,11 @@ static int restore_thread_ctx(int pid, struct thread_ctx *ctx) return ret; } - /* we run at @regs->ip */ static int parasite_trap(struct parasite_ctl *ctl, pid_t pid, user_regs_struct_t *regs, - struct thread_ctx *octx) + struct thread_ctx *octx, + bool may_use_extended_regs) { siginfo_t siginfo; int status; @@ -540,7 +545,7 @@ static int parasite_trap(struct parasite_ctl *ctl, pid_t pid, */ ret = 0; err: - if (restore_thread_ctx(pid, octx)) + if (restore_thread_ctx(pid, octx, may_use_extended_regs)) ret = -1; return ret; @@ -567,7 +572,7 @@ int compel_execute_syscall(struct parasite_ctl *ctl, err = parasite_run(pid, PTRACE_CONT, ctl->ictx.syscall_ip, 0, regs, &ctl->orig); if (!err) - err = parasite_trap(ctl, pid, regs, &ctl->orig); + err = parasite_trap(ctl, pid, regs, &ctl->orig, false); if (ptrace_poke_area(pid, (void *)code_orig, (void *)ctl->ictx.syscall_ip, sizeof(code_orig))) { @@ -585,7 +590,7 @@ int compel_run_at(struct parasite_ctl *ctl, unsigned long ip, user_regs_struct_t ret = parasite_run(ctl->rpid, PTRACE_CONT, ip, 0, ®s, &ctl->orig); if (!ret) - ret = parasite_trap(ctl, ctl->rpid, ret_regs ? ret_regs : ®s, &ctl->orig); + ret = parasite_trap(ctl, ctl->rpid, ret_regs ? ret_regs : ®s, &ctl->orig, false); return ret; } @@ -1471,7 +1476,7 @@ int compel_run_in_thread(struct parasite_thread_ctl *tctl, unsigned int cmd) ret = parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, stack, ®s, octx); if (ret == 0) - ret = parasite_trap(ctl, pid, ®s, octx); + ret = parasite_trap(ctl, pid, ®s, octx, true); if (ret == 0) ret = (int)REG_RES(regs); @@ -1499,7 +1504,11 @@ int compel_unmap(struct parasite_ctl *ctl, unsigned long addr) ret = compel_stop_on_syscall(1, __NR(munmap, 0), __NR(munmap, 1), TRACE_ENTER); - if (restore_thread_ctx(pid, &ctl->orig)) + /* + * Don't touch extended registers here: they were restored + * with rt_sigreturn from sigframe. + */ + if (restore_thread_ctx(pid, &ctl->orig, false)) ret = -1; err: return ret; From 24f57c68d99fecb71ad74bf7578d1f979e2252f4 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 26 Feb 2021 03:05:48 +0000 Subject: [PATCH 133/204] fault-injection: Run fpu corruption tests For the thread leader and for subthreads too. Signed-off-by: Dmitry Safonov --- test/jenkins/criu-fault.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/jenkins/criu-fault.sh b/test/jenkins/criu-fault.sh index f871a140b2..a8c3a5cf7f 100755 --- a/test/jenkins/criu-fault.sh +++ b/test/jenkins/criu-fault.sh @@ -28,3 +28,8 @@ fi ./test/zdtm.py run -t zdtm/static/maps04 --fault 131 --keep-going --report report --pre 2:1 || fail ./test/zdtm.py run -t zdtm/transition/maps008 --fault 131 --keep-going --report report --pre 2:1 || fail ./test/zdtm.py run -t zdtm/static/maps01 --fault 132 -f h || fail +# 134 is corrupting extended registers set, should run in a sub-thread (fpu03) +# without restore (that will check if parasite corrupts extended registers) +./test/zdtm.py run -t zdtm/static/fpu03 --fault 134 -f h --norst || fail +# also check for the main thread corruption +./test/zdtm.py run -t zdtm/static/fpu00 --fault 134 -f h --norst || fail From fc1fefd6e40a41dee4eead12f91d7e5d805b2510 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 26 Feb 2021 03:09:01 +0000 Subject: [PATCH 134/204] s390: Purge stale comment Signed-off-by: Dmitry Safonov --- compel/arch/s390/src/lib/infect.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/compel/arch/s390/src/lib/infect.c b/compel/arch/s390/src/lib/infect.c index 557b21203e..9fad614684 100644 --- a/compel/arch/s390/src/lib/infect.c +++ b/compel/arch/s390/src/lib/infect.c @@ -717,14 +717,6 @@ unsigned long compel_task_size(void) /* * Get task registers (overwrites weak function) - * - * We don't store floating point and vector registers here because we - * assue that compel/pie code does not change them. - * - * For verification issue: - * - * $ objdump -S criu/pie/parasite.built-in.bin.o | grep "%f" - * $ objdump -S criu/pie/restorer.built-in.bin.o | grep "%f" */ int ptrace_get_regs(int pid, user_regs_struct_t *regs) { From 6569412bbd607cf7dcc4cc4983d13a2f754bed43 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Fri, 26 Feb 2021 03:10:35 +0000 Subject: [PATCH 135/204] Revert "compel: add -ffreestanding to force gcc not to use builtin memcpy, memset" This reverts commit c98af78c58e2168d2322cd0ee15837468fd4ffb0. Now FPU/SSE/MMX/etc can be used inside parasite. Let's have compiler optimizations back. Cc: Alexander Mikhalitsyn Signed-off-by: Dmitry Safonov --- compel/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compel/src/main.c b/compel/src/main.c index c5f6e57ed2..2c98659cc7 100644 --- a/compel/src/main.c +++ b/compel/src/main.c @@ -19,7 +19,7 @@ #define CFLAGS_DEFAULT_SET \ "-Wstrict-prototypes " \ - "-fno-stack-protector -nostdlib -fomit-frame-pointer -ffreestanding " + "-fno-stack-protector -nostdlib -fomit-frame-pointer " #define COMPEL_CFLAGS_PIE CFLAGS_DEFAULT_SET "-fpie" #define COMPEL_CFLAGS_NOPIC CFLAGS_DEFAULT_SET "-fno-pic" From 447b3cf61a107acf76f82aca5a4251a01b8323f2 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Tue, 9 Mar 2021 11:17:56 +0000 Subject: [PATCH 136/204] zdtm/fpu03: Add .desc file to omit running on !x86 I managed to forget .desc file and ppc on Jenkins now fails with: > === Run 177/394 =======--------- zdtm/static/fpu03 > timens isn't supported on 5.8.18-100.fc31.ppc64le > ========================== Run zdtm/static/fpu03 in h ========================== > Start test > ./fpu03 --pidfile=fpu03.pid --outfile=fpu03.out > make: *** [Makefile:430: fpu03.pid] Error 1 > Test zdtm/static/fpu03 FAIL at ['make', '--no-print-directory', '-C', 'zdtm/static', 'fpu03.pid'] > Test output: ================================ > 08:56:48.325: 56: SKIP: fpu03.c:116: Unsupported arch > 08:56:48.325: 55: ERR: test.c:316: Test exited unexpectedly with code 0 > > <<< ================================ Signed-off-by: Dmitry Safonov --- test/zdtm/static/fpu03.desc | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/zdtm/static/fpu03.desc diff --git a/test/zdtm/static/fpu03.desc b/test/zdtm/static/fpu03.desc new file mode 100644 index 0000000000..d2f501de20 --- /dev/null +++ b/test/zdtm/static/fpu03.desc @@ -0,0 +1 @@ +{'arch': 'x86_64'} From 1c1949ab53b461b233c2dcac0fe9f15abc0bf532 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 4 Mar 2021 17:41:06 +0000 Subject: [PATCH 137/204] test: move vt test to minor 65 on s390x Our Jenkins s390x vt test fails with ./vt --pidfile=vt.pid --outfile=vt.out --filename=vt.test make: *** [Makefile:432: vt.pid] Error 1 Test zdtm/static/vt FAIL at ['make', '--no-print-directory', '-C', 'zdtm/static', 'vt.pid'] Test output: ================================ 08:08:15.556: 54: ERR: vt.c:38: Open virtual terminal vt.test failed (errno = 6 (No such device or address)) 08:08:15.556: 53: ERR: test.c:316: Test exited unexpectedly with code 1 Because the host has no ttyS0 as used previously. This changes the test to use 'ttysclp0'. That seems to exist on multiple s390x we checked. Signed-off-by: Adrian Reber --- test/zdtm/static/vt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/zdtm/static/vt.c b/test/zdtm/static/vt.c index 0d843c4cf2..6c96fceba9 100644 --- a/test/zdtm/static/vt.c +++ b/test/zdtm/static/vt.c @@ -16,7 +16,7 @@ char *filename; TEST_OPTION(filename, string, "file name", 1); #ifdef __s390x__ -#define MINOR 64 /* ttyS0 */ +#define MINOR 65 /* ttysclp0 */ #else #define MINOR 5 #endif From 77968d43c3641baa189212ee3547e932fff7f634 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Mon, 1 Mar 2021 10:55:18 +0300 Subject: [PATCH 138/204] pstree: check for pid collision before switching to new sid/gid Without this check we can hit the BUG in lookup_create_item just a few steps later (if one thread in images has same pid with new sid/gid). And also this check saves us from different sorts of unexpected errors on restore (if one non-thread task in images has same pid/sid/gid already). Fixes: #1332 Signed-off-by: Pavel Tikhomirov --- criu/pstree.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/criu/pstree.c b/criu/pstree.c index 533f6c0643..e2c130de30 100644 --- a/criu/pstree.c +++ b/criu/pstree.c @@ -339,6 +339,7 @@ static int prepare_pstree_for_shell_job(pid_t pid) pid_t current_gid = getpgid(pid); struct pstree_item *pi; + struct pid *tmp; pid_t old_sid; pid_t old_gid; @@ -371,6 +372,13 @@ static int prepare_pstree_for_shell_job(pid_t pid) pr_info("Migrating process tree (SID %d->%d)\n", old_sid, current_sid); + tmp = pstree_pid_by_virt(current_sid); + if (tmp) { + pr_err("Current sid %d intersects with pid (%d) in images", + current_sid, tmp->state); + return -1; + } + for_each_pstree_item(pi) { if (pi->sid == old_sid) pi->sid = current_sid; @@ -384,6 +392,13 @@ static int prepare_pstree_for_shell_job(pid_t pid) pr_info("Migrating process tree (GID %d->%d)\n", old_gid, current_gid); + tmp = pstree_pid_by_virt(current_gid); + if (tmp) { + pr_err("Current gid %d intersects with pid (%d) in images", + current_gid, tmp->state); + return -1; + } + for_each_pstree_item(pi) { if (pi->pgid == old_gid) pi->pgid = current_gid; From b51fb87a447bf30952ad9371ce30dcb1f0410fd5 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Wed, 3 Feb 2021 23:01:18 +0000 Subject: [PATCH 139/204] ci: move Travis CI Docker tests to GitHub Actions Travis CI is no longer providing CI minutes for open source projects. Signed-off-by: Radostin Stoyanov --- .github/workflows/docker-test.yml | 14 ++++++++++++++ .travis.yml | 13 ------------- scripts/ci/docker-test.sh | 12 ++++-------- 3 files changed, 18 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/docker-test.yml diff --git a/.github/workflows/docker-test.yml b/.github/workflows/docker-test.yml new file mode 100644 index 0000000000..701b646fbf --- /dev/null +++ b/.github/workflows/docker-test.yml @@ -0,0 +1,14 @@ +name: Docker Test + +on: [push, pull_request] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04] + steps: + - uses: actions/checkout@v2 + - name: Run Docker Test (${{ matrix.os }}) + run: sudo make -C scripts/ci docker-test diff --git a/.travis.yml b/.travis.yml index b9b5c643ad..02180ce498 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,19 +30,6 @@ jobs: group: edge virt: vm dist: bionic - - os: linux - arch: amd64 - env: TR_ARCH=docker-test - dist: bionic - - os: linux - arch: amd64 - env: TR_ARCH=docker-test DIST=xenial - # On xenial it should be possible to test overlayfs; - # broken on the latest bionic kernel - dist: xenial - allow_failures: - - env: TR_ARCH=docker-test - - env: TR_ARCH=docker-test DIST=xenial script: - sudo make CCACHE=1 -C scripts/ci $TR_ARCH after_success: diff --git a/scripts/ci/docker-test.sh b/scripts/ci/docker-test.sh index e42e965694..68edfb36b3 100755 --- a/scripts/ci/docker-test.sh +++ b/scripts/ci/docker-test.sh @@ -21,14 +21,10 @@ add-apt-repository \ . /etc/lsb-release -if [ "$DISTRIB_RELEASE" = "18.04" ]; then - # overlayfs behaves differently on Ubuntu (18.04) and breaks CRIU - # https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1857257 - # Switch to devicemapper - echo '{ "experimental": true, "storage-driver": "devicemapper" }' > /etc/docker/daemon.json -else - echo '{ "experimental": true }' > /etc/docker/daemon.json -fi +# overlayfs behaves differently on Ubuntu (18.04) and breaks CRIU +# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1857257 +# Switch to devicemapper +echo '{ "experimental": true, "storage-driver": "devicemapper" }' > /etc/docker/daemon.json service docker restart From 19be9ced929e155a6ca09036a13667b5493c802f Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Wed, 3 Feb 2021 23:33:06 +0000 Subject: [PATCH 140/204] docker-test: use containerd v1.5.0-beta.0 Signed-off-by: Radostin Stoyanov --- scripts/ci/docker-test.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/scripts/ci/docker-test.sh b/scripts/ci/docker-test.sh index 68edfb36b3..0af45a19e1 100755 --- a/scripts/ci/docker-test.sh +++ b/scripts/ci/docker-test.sh @@ -26,6 +26,11 @@ add-apt-repository \ # Switch to devicemapper echo '{ "experimental": true, "storage-driver": "devicemapper" }' > /etc/docker/daemon.json +service docker stop + +# Restore with containerd versions after v1.2.14 and before v1.5.0-beta.0 is broken. +wget -nv https://github.com/containerd/containerd/releases/download/v1.5.0-beta.0/containerd-1.5.0-beta.0-linux-amd64.tar.gz -O - | tar -xz -C /usr/bin/ + service docker restart export SKIP_CI_TEST=1 From fddf3a7327f56809b0715472c9ac70ed3edb8a26 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Wed, 3 Feb 2021 23:48:26 +0000 Subject: [PATCH 141/204] docker-test: set log file path By default docker writes logs in a run-time directory unique for each container. To be able to read this file, we can specify the path in CRIU's configuration file for runc. Signed-off-by: Radostin Stoyanov --- scripts/ci/docker-test.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/ci/docker-test.sh b/scripts/ci/docker-test.sh index 0af45a19e1..466a2c4c70 100755 --- a/scripts/ci/docker-test.sh +++ b/scripts/ci/docker-test.sh @@ -26,6 +26,10 @@ add-apt-repository \ # Switch to devicemapper echo '{ "experimental": true, "storage-driver": "devicemapper" }' > /etc/docker/daemon.json +CRIU_LOG='/criu.log' +mkdir -p /etc/criu +echo "log-file=$CRIU_LOG" > /etc/criu/runc.conf + service docker stop # Restore with containerd versions after v1.2.14 and before v1.5.0-beta.0 is broken. @@ -62,7 +66,7 @@ for i in $(seq 50); do docker start --checkpoint checkpoint"$i" cr 2>&1 | tee log || { cat "$(grep log 'log file:' | sed 's/log file:\s*//')" || true docker logs cr || true - cat /tmp/zdtm-core-* || true + cat $CRIU_LOG || true dmesg docker ps exit 1 From ca2d2737813085ff9bfb83572dcb7429a00fbfe1 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Wed, 3 Mar 2021 23:33:44 +0000 Subject: [PATCH 142/204] lib/cli.py: Open out file as a binary python3 fails to encode image with the following: > [dima@Mindolluin criu]$ ./crit/crit encode -i tmp -o tmp.1 > Traceback (most recent call last): > File "/home/dima/src/criu/./crit/crit", line 6, in > cli.main() > File "/home/dima/src/criu/crit/pycriu/cli.py", line 410, in main > opts["func"](opts) > File "/home/dima/src/criu/crit/pycriu/cli.py", line 50, in encode > pycriu.images.dump(img, outf(opts)) > File "/home/dima/src/criu/crit/pycriu/images/images.py", line 617, in dump > f.write(struct.pack('i', magic.by_name['IMG_COMMON'])) > TypeError: write() argument must be str, not bytes Opening the output file as binary seems to help. Signed-off-by: Dmitry Safonov --- lib/py/cli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/py/cli.py b/lib/py/cli.py index 94cc2f9475..df96729e2e 100755 --- a/lib/py/cli.py +++ b/lib/py/cli.py @@ -16,7 +16,7 @@ def inf(opts): def outf(opts): if opts['out']: - return open(opts['out'], 'w+') + return open(opts['out'], 'wb+') else: return sys.stdout From cdfca869449d1cb8db989644dc4344153011d92a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 10 Mar 2021 15:59:00 +0000 Subject: [PATCH 143/204] ci: remove '-Wl,-z,now' workaround This removes extending LDFLAGS with '-Wl,-z,now'. This was added as workaround but never really worked. It is correctly fixed with pull request #1379 Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index b568ff43f1..0a01f4ce8a 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -136,12 +136,6 @@ if [ "${CD_TO_TOP}" = "1" ]; then cd ../../ fi -if [ "$CLANG" = "1" ]; then - # Needed for clang on Circle CI - LDFLAGS="$LDFLAGS -Wl,-z,now" - export LDFLAGS -fi - export GCOV CC $CC --version time make CC="$CC" -j4 V=1 From 8017b6a8e6356dda1eae841a467c812e8195941e Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 10 Mar 2021 14:57:00 +0000 Subject: [PATCH 144/204] lib: fix recode errors seen in Jenkins Although we are running crit-recode.py also in all CI runs we never seen following error except in Jenkins: Traceback (most recent call last): File "/usr/lib/python3.8/base64.py", line 510, in _input_type_check m = memoryview(s) TypeError: memoryview: a bytes-like object is required, not 'str' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "./test/crit-recode.py", line 25, in recode_and_check r_img = pycriu.images.dumps(pb) File "/var/lib/jenkins/workspace/Q/test/pycriu/images/images.py", line 635, in dumps dump(img, f) File "/var/lib/jenkins/workspace/Q/test/pycriu/images/images.py", line 626, in dump handler.dump(img['entries'], f) File "/var/lib/jenkins/workspace/Q/test/pycriu/images/images.py", line 289, in dump f.write(base64.decodebytes(item['extra'])) File "/usr/lib/python3.8/base64.py", line 545, in decodebytes _input_type_check(s) File "/usr/lib/python3.8/base64.py", line 513, in _input_type_check raise TypeError(msg) from err TypeError: expected bytes-like object, not str This commit fixes this by encoding the string to bytes. Signed-off-by: Adrian Reber --- lib/py/images/images.py | 4 ++-- lib/py/images/pb2dict.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/py/images/images.py b/lib/py/images/images.py index b4b55c9107..85497bdca3 100644 --- a/lib/py/images/images.py +++ b/lib/py/images/images.py @@ -284,9 +284,9 @@ def dump(self, entries, f): size = len(pb_str) f.write(struct.pack('i', size)) f.write(pb_str) - f.write(base64.decodebytes(item['extra'])) + f.write(base64.decodebytes(str.encode(item['extra']))) else: - f.write(base64.decodebytes(item['extra'])) + f.write(base64.decodebytes(str.encode(item['extra']))) def dumps(self, entries): f = io.BytesIO('') diff --git a/lib/py/images/pb2dict.py b/lib/py/images/pb2dict.py index eecdc05223..068d583dc8 100644 --- a/lib/py/images/pb2dict.py +++ b/lib/py/images/pb2dict.py @@ -246,11 +246,11 @@ def encode_dev(field, value): def encode_base64(value): - return base64.encodebytes(value) + return base64.encodebytes(value).decode() def decode_base64(value): - return base64.decodebytes(value) + return base64.decodebytes(str.encode(value)) def encode_unix(value): From 9f2a69691043a1b6ee57a9ed1027139cd21e7913 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 10 Mar 2021 15:42:29 +0000 Subject: [PATCH 145/204] ci: run recode tests on more input files We were running crit-recode in CI only on the output of zdtm/static/env00. This adds zdtm/transition/fork and zdtm/static/ghost_holes00 to run through crit-recode as the image files from those test triggered errors in Jenkins we did not see in CI. Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 0a01f4ce8a..06d6810d72 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -275,7 +275,7 @@ ip net add test ./test/zdtm.py run --empty-ns -T zdtm/static/socket-tcp*-local --iter 2 -./test/zdtm.py run -t zdtm/static/env00 -k always +./test/zdtm.py run -t zdtm/static/env00 -t zdtm/transition/fork -t zdtm/static/ghost_holes00 -k always ./test/crit-recode.py # libcriu testing From b7d2c2a26f97820fac1cb041fcefb308545b1acb Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 10 Mar 2021 07:47:37 +0000 Subject: [PATCH 146/204] ci: remove ccache setup ccache was set up in Travis to speed up compilation by re-using the .ccache directory from previous CI runs. As we are no longer using Travis we can remove all CI related ccache setup. Signed-off-by: Adrian Reber --- .travis.yml | 4 +--- scripts/build/Dockerfile.alpine | 6 ++---- scripts/build/Dockerfile.centos7 | 6 ++---- scripts/build/Dockerfile.centos8 | 6 ++---- scripts/build/Dockerfile.fedora.tmpl | 5 ++--- scripts/build/Dockerfile.linux32.tmpl | 6 ++---- scripts/build/Dockerfile.openj9-alpine | 1 - scripts/build/Dockerfile.tmpl | 6 ++---- scripts/build/Makefile | 6 +----- scripts/ci/prepare-for-fedora-rawhide.sh | 1 - scripts/ci/run-ci-tests.sh | 14 +------------- 11 files changed, 15 insertions(+), 46 deletions(-) diff --git a/.travis.yml b/.travis.yml index 02180ce498..94841b3f3c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,6 @@ language: c os: linux dist: bionic -cache: ccache services: - docker jobs: @@ -31,7 +30,6 @@ jobs: virt: vm dist: bionic script: - - sudo make CCACHE=1 -C scripts/ci $TR_ARCH + - sudo make -C scripts/ci $TR_ARCH after_success: - - ccache -s - make -C scripts/ci after_success diff --git a/scripts/build/Dockerfile.alpine b/scripts/build/Dockerfile.alpine index dbf3c2bf16..058b46ad60 100644 --- a/scripts/build/Dockerfile.alpine +++ b/scripts/build/Dockerfile.alpine @@ -6,7 +6,6 @@ RUN apk update && apk add \ $CC \ bash \ build-base \ - ccache \ coreutils \ git \ gnutls-dev \ @@ -26,9 +25,8 @@ RUN apk update && apk add \ COPY . /criu WORKDIR /criu -ENV CC="ccache $CC" CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes -RUN mv .ccache /tmp && make mrproper && ccache -sz && \ - date && make -j $(nproc) CC="$CC" && date && ccache -s +ENV $ENV1=yes +RUN make mrproper && date && make -j $(nproc) CC="$CC" && date RUN apk add \ ip6tables \ diff --git a/scripts/build/Dockerfile.centos7 b/scripts/build/Dockerfile.centos7 index 213be694fb..d10ec48e14 100644 --- a/scripts/build/Dockerfile.centos7 +++ b/scripts/build/Dockerfile.centos7 @@ -5,7 +5,6 @@ ARG ENV1=FOOBAR RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm RUN yum install -y \ - ccache \ findutils \ gcc \ git \ @@ -39,9 +38,8 @@ RUN yum install -y \ COPY . /criu WORKDIR /criu -ENV CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes -RUN mv .ccache /tmp && make mrproper && ccache -sz && \ - date && make -j $(nproc) CC="$CC" && date && ccache -s +ENV $ENV1=yes +RUN make mrproper && date && make -j $(nproc) CC="$CC" && date # The rpc test cases are running as user #1000, let's add the user RUN adduser -u 1000 test diff --git a/scripts/build/Dockerfile.centos8 b/scripts/build/Dockerfile.centos8 index e3aabbe599..ff6c15f7fd 100644 --- a/scripts/build/Dockerfile.centos8 +++ b/scripts/build/Dockerfile.centos8 @@ -7,7 +7,6 @@ RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.n RUN yum config-manager --set-enabled powertools RUN yum install -y --allowerasing \ asciidoc \ - ccache \ coreutils \ chkconfig \ diffutils \ @@ -44,9 +43,8 @@ ENV PYTHON=python3 COPY . /criu WORKDIR /criu -ENV CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes -RUN mv .ccache /tmp && make mrproper && ccache -sz && \ - date && make -j $(nproc) CC="$CC" && date && ccache -s +ENV $ENV1=yes +RUN make mrproper && date && make -j $(nproc) CC="$CC" && date # The rpc test cases are running as user #1000, let's add the user RUN adduser -u 1000 test diff --git a/scripts/build/Dockerfile.fedora.tmpl b/scripts/build/Dockerfile.fedora.tmpl index 918849a7b0..2ee20ae381 100644 --- a/scripts/build/Dockerfile.fedora.tmpl +++ b/scripts/build/Dockerfile.fedora.tmpl @@ -7,9 +7,8 @@ RUN /bin/prepare-for-fedora-rawhide.sh COPY . /criu WORKDIR /criu -ENV CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes -RUN mv .ccache /tmp && make mrproper && ccache -sz && \ - date && make -j $(nproc) CC="$CC" && date && ccache -s +ENV $ENV1=yes +RUN make mrproper && date && make -j $(nproc) CC="$CC" && date # The rpc test cases are running as user #1000, let's add the user RUN adduser -u 1000 test diff --git a/scripts/build/Dockerfile.linux32.tmpl b/scripts/build/Dockerfile.linux32.tmpl index 49eaeb3b23..cf26b27561 100644 --- a/scripts/build/Dockerfile.linux32.tmpl +++ b/scripts/build/Dockerfile.linux32.tmpl @@ -4,7 +4,6 @@ ARG ENV1=FOOBAR COPY scripts/ci/apt-install /bin/apt-install RUN apt-install \ - ccache \ libnet-dev \ libnl-route-3-dev \ $CC \ @@ -28,12 +27,11 @@ RUN apt-install \ COPY . /criu WORKDIR /criu -ENV CC="ccache $CC" CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes +ENV $ENV1=yes RUN uname -m && setarch linux32 uname -m && setarch --list -RUN mv .ccache /tmp && make mrproper && ccache -s && \ - date && \ +RUN make mrproper && date && \ # Check single object build setarch linux32 make -j $(nproc) CC="$CC" criu/parasite-syscall.o && \ # Compile criu diff --git a/scripts/build/Dockerfile.openj9-alpine b/scripts/build/Dockerfile.openj9-alpine index 873284f44a..5f2f08df46 100644 --- a/scripts/build/Dockerfile.openj9-alpine +++ b/scripts/build/Dockerfile.openj9-alpine @@ -3,7 +3,6 @@ FROM adoptopenjdk/openjdk8-openj9:alpine RUN apk update && apk add \ bash \ build-base \ - ccache \ coreutils \ git \ gnutls-dev \ diff --git a/scripts/build/Dockerfile.tmpl b/scripts/build/Dockerfile.tmpl index 0cb6de3db5..c259796242 100644 --- a/scripts/build/Dockerfile.tmpl +++ b/scripts/build/Dockerfile.tmpl @@ -4,7 +4,6 @@ ARG ENV1=FOOBAR COPY scripts/ci/apt-install /bin/apt-install RUN apt-install \ - ccache \ libnet-dev \ libnl-route-3-dev \ $CC \ @@ -30,10 +29,9 @@ RUN apt-install \ COPY . /criu WORKDIR /criu -ENV CC="ccache $CC" CCACHE_DIR=/tmp/.ccache CCACHE_NOCOMPRESS=1 $ENV1=yes +ENV $ENV1=yes -RUN mv .ccache /tmp && make mrproper && ccache -s && \ - date && \ +RUN make mrproper && date && \ # Check single object build make -j $(nproc) CC="$CC" criu/parasite-syscall.o && \ # Compile criu diff --git a/scripts/build/Makefile b/scripts/build/Makefile index 85bbf2010c..b6c6477f3e 100644 --- a/scripts/build/Makefile +++ b/scripts/build/Makefile @@ -19,10 +19,7 @@ Dockerfile.%: Dockerfile.%.hdr Dockerfile.%.tmpl cat $^ > $@ $(TARGETS): - mkdir -p $(HOME)/.ccache - mv $(HOME)/.ccache ../../ - $(CONTAINER_RUNTIME) build -t criu-$@ -f Dockerfile.$@ $(DB_CC) $(DB_ENV) ../.. - $(CONTAINER_RUNTIME) run criu-$@ tar c -C /tmp .ccache | tar x -C $(HOME) + $(CONTAINER_RUNTIME) build -t criu-$@ -f Dockerfile.$@ $(DB_CC) ../.. .PHONY: $(TARGETS) # Clang builds add some Docker build env @@ -32,6 +29,5 @@ endef $(foreach t,$(TARGETS),$(eval $(call CLANG_DEP,$(t)))) %-clang: DB_CC=--build-arg CC=clang -%-clang: DB_ENV=--build-arg ENV1=CCACHE_CPP2 s390x-clang: DB_CC=--build-arg CC=clang-3.8 .PHONY: $(TARGETS_CLANG) diff --git a/scripts/ci/prepare-for-fedora-rawhide.sh b/scripts/ci/prepare-for-fedora-rawhide.sh index 3ce991dc42..e5900e5637 100755 --- a/scripts/ci/prepare-for-fedora-rawhide.sh +++ b/scripts/ci/prepare-for-fedora-rawhide.sh @@ -2,7 +2,6 @@ set -e -x dnf install -y \ - ccache \ diffutils \ findutils \ gcc \ diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 06d6810d72..ad897a3407 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -4,7 +4,7 @@ set -x -e CI_PKGS="protobuf-c-compiler libprotobuf-c-dev libaio-dev libgnutls28-dev libgnutls30 libprotobuf-dev protobuf-compiler libcap-dev libnl-3-dev gdb bash libnet-dev util-linux asciidoctor - libnl-route-3-dev time ccache flake8 libbsd-dev + libnl-route-3-dev time flake8 libbsd-dev libperl-dev pkg-config" @@ -64,16 +64,6 @@ ci_prep () { fi CI_PKGS="$CI_PKGS $CC" - # ccache support, only enable for non-GCOV case - if [ "$CCACHE" = "1" ] && [ -z "$GCOV" ]; then - # ccache is installed by default, need to set it up - export CCACHE_DIR=$HOME/.ccache - [ "$CC" = "clang" ] && export CCACHE_CPP2=yes - # uncomment the following to get detailed ccache logs - #export CCACHE_LOGFILE=$HOME/ccache.log - CC="ccache $CC" - fi - # Do not install x86_64 specific packages on other architectures if [ "$UNAME_M" = "x86_64" ]; then CI_PKGS="$CI_PKGS $X86_64_PKGS" @@ -189,8 +179,6 @@ if [ "${COMPAT_TEST}x" = "yx" ] ; then file test/zdtm/static/env00 | grep 'ELF 32-bit' -q fi -[ -f "$CCACHE_LOGFILE" ] && cat "$CCACHE_LOGFILE" - # umask has to be called before a first criu run, so that .gcda (coverage data) # files are created with read-write permissions for all. umask 0000 From 628ff18fce955f5f98ee553790c845ac7c504997 Mon Sep 17 00:00:00 2001 From: Zeyad Yasser Date: Fri, 22 Jan 2021 01:08:59 +0200 Subject: [PATCH 147/204] ci: run zdtm/transition/pid_reuse with pre-dumps in ci tests This test should be run with at least 1 pre-dump to trigger the problem as mentioned in commit 4d9bf608b59b6e323f346b0beb956b02ecbef294. Signed-off-by: Zeyad Yasser --- scripts/ci/run-ci-tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index ad897a3407..61413cc394 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -251,6 +251,8 @@ make -C test/others/rpc/ run ./test/zdtm.py run -t zdtm/transition/maps007 --pre 2 --page-server ./test/zdtm.py run -t zdtm/transition/maps007 --pre 2 --page-server --dedup +./test/zdtm.py run -t zdtm/transition/pid_reuse --pre 2 + ./test/zdtm.py run -t zdtm/static/socket-tcp-local --norst ip net add test From 42df84994a514abbb9b70dcb4ecb49fbba0eab6e Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 21 Dec 2020 20:12:44 +0000 Subject: [PATCH 148/204] criu-ns: Convert indentation to spaces Spaces are the preferred indentation method. https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 264 ++++++++++++++++++++++++------------------------ 1 file changed, 132 insertions(+), 132 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 05635b1605..5f8e17be00 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -18,190 +18,190 @@ MS_SLAVE = 1 << 19 _libc = ctypes.CDLL(ctypes.util.find_library("c"), use_errno=True) try: - _unshare = _libc.unshare + _unshare = _libc.unshare except AttributeError: - raise OSError(errno.EINVAL, "unshare is not supported on this platform") + raise OSError(errno.EINVAL, "unshare is not supported on this platform") else: - _unshare.argtypes = [ ctypes.c_int ] - _unshare.restype = ctypes.c_int + _unshare.argtypes = [ ctypes.c_int ] + _unshare.restype = ctypes.c_int try: - _setns = _libc.setns + _setns = _libc.setns except AttributeError: - raise OSError(errno.EINVAL, "setns is not supported on this platform") + raise OSError(errno.EINVAL, "setns is not supported on this platform") else: - _setns.argtypes = [ ctypes.c_int, ctypes.c_int ] - _setns.restype = ctypes.c_int + _setns.argtypes = [ ctypes.c_int, ctypes.c_int ] + _setns.restype = ctypes.c_int try: - _mount = _libc.mount + _mount = _libc.mount except AttributeError: - raise OSError(errno.EINVAL, "mount is not supported on this platform") + raise OSError(errno.EINVAL, "mount is not supported on this platform") else: - _mount.argtypes = [ - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_char_p, - ctypes.c_ulong, - ctypes.c_void_p - ] - _mount.restype = ctypes.c_int + _mount.argtypes = [ + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_char_p, + ctypes.c_ulong, + ctypes.c_void_p + ] + _mount.restype = ctypes.c_int try: - _umount = _libc.umount + _umount = _libc.umount except AttributeError: - raise OSError(errno.EINVAL, "umount is not supported on this platform") + raise OSError(errno.EINVAL, "umount is not supported on this platform") else: - _umount.argtypes = [ctypes.c_char] - _umount.restype = ctypes.c_int + _umount.argtypes = [ctypes.c_char] + _umount.restype = ctypes.c_int def run_criu(): - print(sys.argv) - os.execlp('criu', *['criu'] + sys.argv[1:]) + print(sys.argv) + os.execlp('criu', *['criu'] + sys.argv[1:]) def wrap_restore(): - # Unshare pid and mount namespaces - if _unshare(CLONE_NEWNS | CLONE_NEWPID) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) - - criu_pid = os.fork() - if criu_pid == 0: - # Mount new /proc - if _mount(None, b"/", None, MS_SLAVE|MS_REC, None) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) - - if _mount(b'proc', b'/proc', b'proc', 0, None) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) - - # Spawn CRIU binary - run_criu() - raise OSError(errno.ENOENT, "No such command") - - # Wait for CRIU to exit and report the status back - while True: - try: - (pid, status) = os.wait() - if pid == criu_pid: - status = os.WEXITSTATUS(status) - break - except OSError: - status = -251 - break - - return status + # Unshare pid and mount namespaces + if _unshare(CLONE_NEWNS | CLONE_NEWPID) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + criu_pid = os.fork() + if criu_pid == 0: + # Mount new /proc + if _mount(None, b"/", None, MS_SLAVE|MS_REC, None) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + if _mount(b'proc', b'/proc', b'proc', 0, None) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + # Spawn CRIU binary + run_criu() + raise OSError(errno.ENOENT, "No such command") + + # Wait for CRIU to exit and report the status back + while True: + try: + (pid, status) = os.wait() + if pid == criu_pid: + status = os.WEXITSTATUS(status) + break + except OSError: + status = -251 + break + + return status def get_varg(args): - for i in range(1, len(sys.argv)): - if not sys.argv[i] in args: - continue + for i in range(1, len(sys.argv)): + if not sys.argv[i] in args: + continue - if i + 1 >= len(sys.argv): - break + if i + 1 >= len(sys.argv): + break - return (sys.argv[i + 1], i + 1) + return (sys.argv[i + 1], i + 1) - return (None, None) + return (None, None) def set_pidns(tpid, pid_idx): - # Joind pid namespace. Note, that the given pid should - # be changed in -t option, as task lives in different - # pid namespace. + # Joind pid namespace. Note, that the given pid should + # be changed in -t option, as task lives in different + # pid namespace. - myns = os.stat('/proc/self/ns/pid').st_ino + myns = os.stat('/proc/self/ns/pid').st_ino - ns_fd = os.open('/proc/%s/ns/pid' % tpid, os.O_RDONLY) - if myns != os.fstat(ns_fd).st_ino: + ns_fd = os.open('/proc/%s/ns/pid' % tpid, os.O_RDONLY) + if myns != os.fstat(ns_fd).st_ino: - for l in open('/proc/%s/status' % tpid): - if not l.startswith('NSpid:'): - continue + for l in open('/proc/%s/status' % tpid): + if not l.startswith('NSpid:'): + continue - ls = l.split() - if ls[1] != tpid: - raise OSError(errno.ESRCH, 'No such pid') + ls = l.split() + if ls[1] != tpid: + raise OSError(errno.ESRCH, 'No such pid') - print('Replace pid {} with {}'.format(tpid, ls[2])) - sys.argv[pid_idx] = ls[2] - break - else: - raise OSError(errno.ENOENT, 'Cannot find NSpid field in proc') + print('Replace pid {} with {}'.format(tpid, ls[2])) + sys.argv[pid_idx] = ls[2] + break + else: + raise OSError(errno.ENOENT, 'Cannot find NSpid field in proc') - if _setns(ns_fd, 0) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) + if _setns(ns_fd, 0) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) - os.close(ns_fd) + os.close(ns_fd) def set_mntns(tpid): - # Join mount namespace. Trick here too -- check / and . - # will be the same in target mntns. + # Join mount namespace. Trick here too -- check / and . + # will be the same in target mntns. - myns = os.stat('/proc/self/ns/mnt').st_ino - ns_fd = os.open('/proc/%s/ns/mnt' % tpid, os.O_RDONLY) - if myns != os.fstat(ns_fd).st_ino: - root_st = os.stat('/') - cwd_st = os.stat('.') - cwd_path = os.path.realpath('.') + myns = os.stat('/proc/self/ns/mnt').st_ino + ns_fd = os.open('/proc/%s/ns/mnt' % tpid, os.O_RDONLY) + if myns != os.fstat(ns_fd).st_ino: + root_st = os.stat('/') + cwd_st = os.stat('.') + cwd_path = os.path.realpath('.') - if _setns(ns_fd, 0) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) + if _setns(ns_fd, 0) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) - os.chdir(cwd_path) - root_nst = os.stat('/') - cwd_nst = os.stat('.') + os.chdir(cwd_path) + root_nst = os.stat('/') + cwd_nst = os.stat('.') - def steq(st, nst): - return (st.st_dev, st.st_ino) == (nst.st_dev, nst.st_ino) + def steq(st, nst): + return (st.st_dev, st.st_ino) == (nst.st_dev, nst.st_ino) - if not steq(root_st, root_nst): - raise OSError(errno.EXDEV, 'Target ns / is not as current') - if not steq(cwd_st, cwd_nst): - raise OSError(errno.EXDEV, 'Target ns . is not as current') + if not steq(root_st, root_nst): + raise OSError(errno.EXDEV, 'Target ns / is not as current') + if not steq(cwd_st, cwd_nst): + raise OSError(errno.EXDEV, 'Target ns . is not as current') - os.close(ns_fd) + os.close(ns_fd) def wrap_dump(): - (pid, pid_idx) = get_varg(('-t', '--tree')) - if pid is None: - raise OSError(errno.EINVAL, 'No --tree option given') + (pid, pid_idx) = get_varg(('-t', '--tree')) + if pid is None: + raise OSError(errno.EINVAL, 'No --tree option given') - set_pidns(pid, pid_idx) - set_mntns(pid) + set_pidns(pid, pid_idx) + set_mntns(pid) - # Spawn CRIU binary - criu_pid = os.fork() - if criu_pid == 0: - run_criu() - raise OSError(errno.ENOENT, "No such command") + # Spawn CRIU binary + criu_pid = os.fork() + if criu_pid == 0: + run_criu() + raise OSError(errno.ENOENT, "No such command") - # Wait for CRIU to exit and report the status back - while True: - try: - (pid, status) = os.wait() - if pid == criu_pid: - status = os.WEXITSTATUS(status) - break - except OSError: - status = -251 - break + # Wait for CRIU to exit and report the status back + while True: + try: + (pid, status) = os.wait() + if pid == criu_pid: + status = os.WEXITSTATUS(status) + break + except OSError: + status = -251 + break - return status + return status if len(sys.argv) == 1: - print(""" + print(""" Usage: {0} dump|pre-dump -t PID [] {0} restore [] @@ -210,16 +210,16 @@ Usage: pre-dump pre-dump task(s) minimizing their frozen time restore restore a process/tree """.format(sys.argv[0])) - exit(1) + exit(1) action = sys.argv[1] if action == 'restore': - res = wrap_restore() + res = wrap_restore() elif action == 'dump' or action == 'pre-dump': - res = wrap_dump() + res = wrap_dump() else: - print('Unsupported action {} for nswrap'.format(action)) - res = -1 + print('Unsupported action {} for nswrap'.format(action)) + res = -1 sys.exit(res) From a6659c3a7c893a7ba627dc7a78f6d48f0177e874 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 21 Dec 2020 20:15:05 +0000 Subject: [PATCH 149/204] criu-ns: Remove space before/after bracket Avoid extraneous whitespace. https://python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 5f8e17be00..de9308035b 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -22,7 +22,7 @@ try: except AttributeError: raise OSError(errno.EINVAL, "unshare is not supported on this platform") else: - _unshare.argtypes = [ ctypes.c_int ] + _unshare.argtypes = [ctypes.c_int] _unshare.restype = ctypes.c_int try: @@ -30,7 +30,7 @@ try: except AttributeError: raise OSError(errno.EINVAL, "setns is not supported on this platform") else: - _setns.argtypes = [ ctypes.c_int, ctypes.c_int ] + _setns.argtypes = [ctypes.c_int, ctypes.c_int] _setns.restype = ctypes.c_int try: From c7d76082c3b4337fbf8737dd6478620f73f09972 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 21 Dec 2020 20:25:47 +0000 Subject: [PATCH 150/204] criu-ns: Extract mount new /proc into a function By extracting this code into a function the main code becomes smaller and more obvious. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index de9308035b..89e52c9ab8 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -56,6 +56,18 @@ else: _umount.restype = ctypes.c_int +def _mount_new_proc(): + """ + Mount new /proc filesystem. + """ + if _mount(None, b"/", None, MS_SLAVE|MS_REC, None): + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + if _mount(b'proc', b'/proc', b'proc', 0, None): + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + def run_criu(): print(sys.argv) os.execlp('criu', *['criu'] + sys.argv[1:]) @@ -69,14 +81,7 @@ def wrap_restore(): criu_pid = os.fork() if criu_pid == 0: - # Mount new /proc - if _mount(None, b"/", None, MS_SLAVE|MS_REC, None) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) - - if _mount(b'proc', b'/proc', b'proc', 0, None) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) + _mount_new_proc() # Spawn CRIU binary run_criu() From 097834dad00580b5baaebb76b15abdab1428635c Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 21 Dec 2020 20:31:50 +0000 Subject: [PATCH 151/204] criu-ns: Extract wait for process into a function Reduce duplication of code. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 89e52c9ab8..183f4485bf 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -68,6 +68,19 @@ def _mount_new_proc(): raise OSError(_errno, errno.errorcode[_errno]) +def _wait_for_process_status(criu_pid): + """ + Wait for CRIU to exit and report the status back. + """ + while True: + try: + (pid, status) = os.wait() + if pid == criu_pid: + return os.WEXITSTATUS(status) + except OSError: + return -251 + + def run_criu(): print(sys.argv) os.execlp('criu', *['criu'] + sys.argv[1:]) @@ -87,18 +100,7 @@ def wrap_restore(): run_criu() raise OSError(errno.ENOENT, "No such command") - # Wait for CRIU to exit and report the status back - while True: - try: - (pid, status) = os.wait() - if pid == criu_pid: - status = os.WEXITSTATUS(status) - break - except OSError: - status = -251 - break - - return status + return _wait_for_process_status(criu_pid) def get_varg(args): @@ -191,18 +193,7 @@ def wrap_dump(): run_criu() raise OSError(errno.ENOENT, "No such command") - # Wait for CRIU to exit and report the status back - while True: - try: - (pid, status) = os.wait() - if pid == criu_pid: - status = os.WEXITSTATUS(status) - break - except OSError: - status = -251 - break - - return status + return _wait_for_process_status(pid) if len(sys.argv) == 1: From b790ce21ef8c8f234062f02935ed59ed20b5e406 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 21 Dec 2020 20:50:18 +0000 Subject: [PATCH 152/204] criu-ns: Use documentation strings Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 183f4485bf..7cbf0b1418 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -82,6 +82,9 @@ def _wait_for_process_status(criu_pid): def run_criu(): + """ + Spawn CRIU binary + """ print(sys.argv) os.execlp('criu', *['criu'] + sys.argv[1:]) @@ -96,7 +99,6 @@ def wrap_restore(): if criu_pid == 0: _mount_new_proc() - # Spawn CRIU binary run_criu() raise OSError(errno.ENOENT, "No such command") @@ -118,12 +120,12 @@ def get_varg(args): def set_pidns(tpid, pid_idx): - # Joind pid namespace. Note, that the given pid should - # be changed in -t option, as task lives in different - # pid namespace. - + """ + Join pid namespace. Note, that the given pid should + be changed in -t option, as task lives in different + pid namespace. + """ myns = os.stat('/proc/self/ns/pid').st_ino - ns_fd = os.open('/proc/%s/ns/pid' % tpid, os.O_RDONLY) if myns != os.fstat(ns_fd).st_ino: @@ -149,9 +151,10 @@ def set_pidns(tpid, pid_idx): def set_mntns(tpid): - # Join mount namespace. Trick here too -- check / and . - # will be the same in target mntns. - + """ + Join mount namespace. Trick here too -- check / and . + will be the same in target mntns. + """ myns = os.stat('/proc/self/ns/mnt').st_ino ns_fd = os.open('/proc/%s/ns/mnt' % tpid, os.O_RDONLY) if myns != os.fstat(ns_fd).st_ino: @@ -187,7 +190,6 @@ def wrap_dump(): set_pidns(pid, pid_idx) set_mntns(pid) - # Spawn CRIU binary criu_pid = os.fork() if criu_pid == 0: run_criu() From ab9418d96ca289bb70998147ad8478631f9c5a7e Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Mon, 21 Dec 2020 20:59:45 +0000 Subject: [PATCH 153/204] criu-ns: Remove unused _umount Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 8 -------- 1 file changed, 8 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 7cbf0b1418..7808b02ccc 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -47,14 +47,6 @@ else: ] _mount.restype = ctypes.c_int -try: - _umount = _libc.umount -except AttributeError: - raise OSError(errno.EINVAL, "umount is not supported on this platform") -else: - _umount.argtypes = [ctypes.c_char] - _umount.restype = ctypes.c_int - def _mount_new_proc(): """ From 44a1d321bf717c30192e2f8bcbf22be9ee749b56 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 22 Dec 2020 11:46:03 +0000 Subject: [PATCH 154/204] criu-ns: Extract set namespace functions This change extracts some of the duplicated code from set_pidns() and set_mntns() functions. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 7808b02ccc..f8a8e6ce59 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -110,6 +110,17 @@ def get_varg(args): return (None, None) +def _set_namespace(fd): + """Join namespace referred to by fd""" + if _setns(fd, 0) != 0: + _errno = ctypes.get_errno() + raise OSError(_errno, errno.errorcode[_errno]) + + +def is_my_namespace(fd): + """Returns True if fd refers to current namespace""" + return os.stat('/proc/self/ns/pid').st_ino != os.fstat(fd).st_ino + def set_pidns(tpid, pid_idx): """ @@ -117,14 +128,11 @@ def set_pidns(tpid, pid_idx): be changed in -t option, as task lives in different pid namespace. """ - myns = os.stat('/proc/self/ns/pid').st_ino ns_fd = os.open('/proc/%s/ns/pid' % tpid, os.O_RDONLY) - if myns != os.fstat(ns_fd).st_ino: - + if is_my_namespace(ns_fd): for l in open('/proc/%s/status' % tpid): if not l.startswith('NSpid:'): continue - ls = l.split() if ls[1] != tpid: raise OSError(errno.ESRCH, 'No such pid') @@ -134,11 +142,7 @@ def set_pidns(tpid, pid_idx): break else: raise OSError(errno.ENOENT, 'Cannot find NSpid field in proc') - - if _setns(ns_fd, 0) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) - + _set_namespace(ns_fd) os.close(ns_fd) @@ -147,16 +151,13 @@ def set_mntns(tpid): Join mount namespace. Trick here too -- check / and . will be the same in target mntns. """ - myns = os.stat('/proc/self/ns/mnt').st_ino ns_fd = os.open('/proc/%s/ns/mnt' % tpid, os.O_RDONLY) - if myns != os.fstat(ns_fd).st_ino: + if is_my_namespace(ns_fd): root_st = os.stat('/') cwd_st = os.stat('.') cwd_path = os.path.realpath('.') - if _setns(ns_fd, 0) != 0: - _errno = ctypes.get_errno() - raise OSError(_errno, errno.errorcode[_errno]) + _set_namespace(ns_fd) os.chdir(cwd_path) root_nst = os.stat('/') @@ -169,8 +170,6 @@ def set_mntns(tpid): raise OSError(errno.EXDEV, 'Target ns / is not as current') if not steq(cwd_st, cwd_nst): raise OSError(errno.EXDEV, 'Target ns . is not as current') - - os.close(ns_fd) From b31d3ad9278c0d07c7b2562c387f5c659af32b6e Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Sun, 17 Jan 2021 13:05:42 +0000 Subject: [PATCH 155/204] criu-ns: Close namespace fd before raise It is a good practice to close open file descriptors. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/criu-ns b/scripts/criu-ns index f8a8e6ce59..e94bfcfbf3 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -135,12 +135,14 @@ def set_pidns(tpid, pid_idx): continue ls = l.split() if ls[1] != tpid: + os.close(ns_fd) raise OSError(errno.ESRCH, 'No such pid') print('Replace pid {} with {}'.format(tpid, ls[2])) sys.argv[pid_idx] = ls[2] break else: + os.close(ns_fd) raise OSError(errno.ENOENT, 'Cannot find NSpid field in proc') _set_namespace(ns_fd) os.close(ns_fd) @@ -167,8 +169,10 @@ def set_mntns(tpid): return (st.st_dev, st.st_ino) == (nst.st_dev, nst.st_ino) if not steq(root_st, root_nst): + os.close(ns_fd) raise OSError(errno.EXDEV, 'Target ns / is not as current') if not steq(cwd_st, cwd_nst): + os.close(ns_fd) raise OSError(errno.EXDEV, 'Target ns . is not as current') os.close(ns_fd) From 6055d0be74fc9d5ec1e4cace3bbaf76092868029 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 22 Dec 2020 11:57:58 +0000 Subject: [PATCH 156/204] criu-ns: Pass arguments to run_criu() Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index e94bfcfbf3..f9623fb7f9 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -73,12 +73,13 @@ def _wait_for_process_status(criu_pid): return -251 -def run_criu(): +def run_criu(args): """ Spawn CRIU binary """ print(sys.argv) - os.execlp('criu', *['criu'] + sys.argv[1:]) + os.execlp('criu', *['criu'] + args) + raise OSError(errno.ENOENT, "No such command") def wrap_restore(): @@ -90,10 +91,7 @@ def wrap_restore(): criu_pid = os.fork() if criu_pid == 0: _mount_new_proc() - - run_criu() - raise OSError(errno.ENOENT, "No such command") - + run_criu(sys.argv[1:]) return _wait_for_process_status(criu_pid) @@ -187,9 +185,7 @@ def wrap_dump(): criu_pid = os.fork() if criu_pid == 0: - run_criu() - raise OSError(errno.ENOENT, "No such command") - + run_criu(sys.argv[1:]) return _wait_for_process_status(pid) From 719c5b07e036a4b7abc0e82ed4f668a1d3a247e1 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 22 Dec 2020 12:15:54 +0000 Subject: [PATCH 157/204] criu-ns: Handle restore-detached option The criu-ns script creates a new PID namespace where criu is the "init" process. When using the --restore-detached option with criu-ns, users expect criu-ns to exit without killing the restored process tree. Thus, criu-ns should not pass the --restore-detached to criu to prevent it from terminating, and it should exit instead of waiting for criu's exit status. Resolves #1278 Suggested-by: Andrei Vagin Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index f9623fb7f9..0c753347b0 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -88,10 +88,23 @@ def wrap_restore(): _errno = ctypes.get_errno() raise OSError(_errno, errno.errorcode[_errno]) + restore_detached = False + restore_args = sys.argv[1:] + if '-d' in restore_args: + restore_detached = True + restore_args.remove('-d') + if '--restore-detached' in restore_args: + restore_detached = True + restore_args.remove('--restore-detached') + criu_pid = os.fork() if criu_pid == 0: _mount_new_proc() - run_criu(sys.argv[1:]) + run_criu(restore_args) + + if restore_detached: + return 0 + return _wait_for_process_status(criu_pid) From 66f5ab4392598a270571e5cd2c2025578894fe69 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 22 Dec 2020 12:26:03 +0000 Subject: [PATCH 158/204] criu-ns: Add unsupported msg for restore-sibling Currently criu-ns does not support the --restore-sibling option. Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 0c753347b0..68ced5ec86 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -83,13 +83,16 @@ def run_criu(args): def wrap_restore(): + restore_args = sys.argv[1:] + if '--restore-sibling' in restore_args: + raise OSError(errno.EINVAL, "--restore-sibling is not supported") + # Unshare pid and mount namespaces if _unshare(CLONE_NEWNS | CLONE_NEWPID) != 0: _errno = ctypes.get_errno() raise OSError(_errno, errno.errorcode[_errno]) restore_detached = False - restore_args = sys.argv[1:] if '-d' in restore_args: restore_detached = True restore_args.remove('-d') From d49ace9d34a259c5439f5bc1b81fe134b551b154 Mon Sep 17 00:00:00 2001 From: Radostin Stoyanov Date: Tue, 22 Dec 2020 12:31:30 +0000 Subject: [PATCH 159/204] criu-ns: Merge comparisons with 'in' Signed-off-by: Radostin Stoyanov --- scripts/criu-ns | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/criu-ns b/scripts/criu-ns index 68ced5ec86..3ee6564e93 100755 --- a/scripts/criu-ns +++ b/scripts/criu-ns @@ -221,7 +221,7 @@ action = sys.argv[1] if action == 'restore': res = wrap_restore() -elif action == 'dump' or action == 'pre-dump': +elif action in ['dump', 'pre-dump']: res = wrap_dump() else: print('Unsupported action {} for nswrap'.format(action)) From 02b0e850dac3e106357296df86d8537fe21af42d Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 15 Mar 2021 14:16:14 +0000 Subject: [PATCH 160/204] lib: fromstring() and tostring() are deprecated fromstring() and tostring() are deprecated since Python 3.2 and have been removed in 3.9. Both functions were just aliases and this patch changes images.py to directly call fromybytes() and tobytes(). Signed-off-by: Adrian Reber --- lib/py/images/images.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/py/images/images.py b/lib/py/images/images.py index 85497bdca3..c854c6152b 100644 --- a/lib/py/images/images.py +++ b/lib/py/images/images.py @@ -375,7 +375,7 @@ def load(self, f, pbuff): s = array.array('H') if s.itemsize != sizeof_u16: raise Exception("Array size mismatch") - s.fromstring(f.read(size)) + s.frombytes(f.read(size)) f.seek(rounded - size, 1) return s.tolist() @@ -389,7 +389,7 @@ def dump(self, extra, f, pbuff): s.fromlist(extra) if len(s) != entry['nsems']: raise Exception("Number of semaphores mismatch") - f.write(s.tostring()) + f.write(s.tobytes()) f.write('\0' * (rounded - size)) def skip(self, f, pbuff): From c8beca65580da87b89964da3ffb454ca99aa6bc6 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 15 Mar 2021 14:30:04 +0000 Subject: [PATCH 161/204] lib: correctly handle padding of dump images With the switch to Python3 and binary output it is not possible to use code like: 'f.write('\0' * (rounded - size))'. Switching to binary helps. Signed-off-by: Adrian Reber --- lib/py/images/images.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/py/images/images.py b/lib/py/images/images.py index c854c6152b..e4f9ca3d4d 100644 --- a/lib/py/images/images.py +++ b/lib/py/images/images.py @@ -390,7 +390,7 @@ def dump(self, extra, f, pbuff): if len(s) != entry['nsems']: raise Exception("Number of semaphores mismatch") f.write(s.tobytes()) - f.write('\0' * (rounded - size)) + f.write(b'\0' * (rounded - size)) def skip(self, f, pbuff): entry = pb2dict.pb2dict(pbuff) @@ -428,7 +428,7 @@ def dump(self, extra, f, pbuff): rounded = round_up(msg.msize, sizeof_u64) data = base64.decodebytes(extra[i + 1]) f.write(data[:msg.msize]) - f.write('\0' * (rounded - msg.msize)) + f.write(b'\0' * (rounded - msg.msize)) def skip(self, f, pbuff): entry = pb2dict.pb2dict(pbuff) @@ -462,7 +462,7 @@ def dump(self, extra, f, pbuff): data = base64.decodebytes(extra) rounded = round_up(size, sizeof_u32) f.write(data[:size]) - f.write('\0' * (rounded - size)) + f.write(b'\0' * (rounded - size)) def skip(self, f, pbuff): entry = pb2dict.pb2dict(pbuff) From d334ba38d8cf4e3bfa9f113e1d78947fc2f62566 Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Wed, 17 Mar 2021 15:37:31 +0300 Subject: [PATCH 162/204] pstree: don't change sid/gid-s if current sid/gid is the same Previously we only skipped replacing sid for shell job if root_item was session leader, but there is other case where root_item sid is the same as current_sid we can safely skip replacing for this case. Same applies to gid-s. Now after we have pid collision check we not only "can" but should skip pid collision checks for the latter case. It is quite obvious that there are tasks in tree with sid==current_sid if current_sid==old_sid. Fixes: #1400 Fixes: 77968d43c ("pstree: check for pid collision before switching to new sid/gid") Signed-off-by: Pavel Tikhomirov --- criu/pstree.c | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/criu/pstree.c b/criu/pstree.c index e2c130de30..3ca8908b47 100644 --- a/criu/pstree.c +++ b/criu/pstree.c @@ -347,6 +347,7 @@ static int prepare_pstree_for_shell_job(pid_t pid) if (!opts.shell_job) return 0; + /* root_item is a session leader */ if (root_item->sid == vpid(root_item)) return 0; @@ -368,27 +369,32 @@ static int prepare_pstree_for_shell_job(pid_t pid) */ old_sid = root_item->sid; + if (old_sid != current_sid) { + pr_info("Migrating process tree (SID %d->%d)\n", + old_sid, current_sid); - pr_info("Migrating process tree (SID %d->%d)\n", - old_sid, current_sid); - - tmp = pstree_pid_by_virt(current_sid); - if (tmp) { - pr_err("Current sid %d intersects with pid (%d) in images", - current_sid, tmp->state); - return -1; - } + tmp = pstree_pid_by_virt(current_sid); + if (tmp) { + pr_err("Current sid %d intersects with pid (%d) in images", + current_sid, tmp->state); + return -1; + } - for_each_pstree_item(pi) { - if (pi->sid == old_sid) - pi->sid = current_sid; - } + for_each_pstree_item(pi) { + if (pi->sid == old_sid) + pi->sid = current_sid; + } - old_gid = root_item->pgid; - if (old_gid != vpid(root_item)) { if (lookup_create_item(current_sid) == NULL) return -1; + } + /* root_item is a group leader */ + if (root_item->pgid == vpid(root_item)) + return 0; + + old_gid = root_item->pgid; + if (old_gid != current_gid) { pr_info("Migrating process tree (GID %d->%d)\n", old_gid, current_gid); From 9b0d7527910486a2dea23885fb2663f7102daed1 Mon Sep 17 00:00:00 2001 From: fedor Date: Wed, 17 Mar 2021 07:49:26 -0400 Subject: [PATCH 163/204] Use a real VM instead of a privileged container --- .cirrus.yml | 18 +++++++++++------- scripts/ci/vagrant.sh | 24 +----------------------- 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index dce5ce8cdb..a3f401ddb7 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,16 +1,20 @@ environment: + HOME: "/root" CIRRUS_WORKING_DIR: "/tmp/criu" -container: - # This test case does not work on focal, because the newer version - # of libvirt fails during 'vagrant up' with ip6tables errors. - image: ubuntu:bionic - kvm: true + +compute_engine_instance: + image_project: cirrus-images + image: family/docker-kvm + platform: linux cpu: 4 - memory: 8G + memory: 16G + nested_virtualization: true + task: name: Vagrant Fedora based test (no VDSO) setup_script: | - scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget + scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker + sudo kvm-ok ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto build_script: | make -C scripts/ci vagrant-fedora-no-vdso diff --git a/scripts/ci/vagrant.sh b/scripts/ci/vagrant.sh index 4dccf2613b..3ed1a26754 100755 --- a/scripts/ci/vagrant.sh +++ b/scripts/ci/vagrant.sh @@ -15,13 +15,6 @@ setup() { # Load the kvm modules for vagrant to use qemu modprobe kvm kvm_intel fi - if [ -n "$CIRRUS_CI" ]; then - # Running modprobe is not possible on Cirrus, because - # we are running in a container with potentially other - # modules than the host. - # Vagrant can still use /dev/kvm later if we do - chmod 666 /dev/kvm - fi # Tar up the git checkout to have vagrant rsync it to the VM tar cf criu.tar ../../../criu @@ -32,28 +25,13 @@ setup() { ./apt-install libvirt-clients libvirt-daemon-system libvirt-dev qemu-utils qemu \ ruby build-essential libxml2-dev qemu-kvm rsync ebtables dnsmasq-base \ openssh-client - if [ -n "$CIRRUS_CI" ]; then - # On Cirrus systemctl does not work, because we are running in - # a container without access to systemd - /usr/sbin/virtlogd -d - /usr/sbin/libvirtd -d - else - systemctl restart libvirtd - fi + systemctl restart libvirtd vagrant plugin install vagrant-libvirt vagrant init fedora/${FEDORA_VERSION}-cloud-base --box-version ${FEDORA_BOX_VERSION} # The default libvirt Vagrant VM uses 512MB. # Travis VMs should have around 7.5GB. # Increasing it to 4GB should work. sed -i Vagrantfile -e 's,^end$, config.vm.provider :libvirt do |libvirt|'"\n"' libvirt.memory = 4096;end'"\n"'end,g' - if [ -n "$CIRRUS_CI" ]; then - # Work around for: - # Error while activating network: Call to virNetworkCreate failed: internal error: - # Failed to apply firewall rules /usr/sbin/ip6tables --table filter --list-rules: modprobe: FATAL: Module ip6_tables not found in directory /lib/modules/5.4.0-1025-gcp - # On cirrus-ci.com. Running in a container without access to the host's kernel modules - rm -f /sbin/ip6tables - cp /bin/true /sbin/ip6tables - fi vagrant up --provider=libvirt --no-tty mkdir -p /root/.ssh vagrant ssh-config >> /root/.ssh/config From ca032081e3d3cfa8a0231b82b0b0b9398479ef11 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 19 Mar 2021 08:57:04 +0000 Subject: [PATCH 164/204] ci: move CentOS 8 based test to Cirrus The kernel on GitHub Actions has a bug https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1919472 which breaks our CI. It works on Cirrus. Let's move it there. Signed-off-by: Adrian Reber --- .cirrus.yml | 57 ++++++++++++++++++++++++------- .github/workflows/centos-test.yml | 2 +- scripts/ci/run-ci-tests.sh | 2 +- 3 files changed, 47 insertions(+), 14 deletions(-) diff --git a/.cirrus.yml b/.cirrus.yml index a3f401ddb7..5574b15835 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -1,20 +1,53 @@ -environment: - HOME: "/root" - CIRRUS_WORKING_DIR: "/tmp/criu" - -compute_engine_instance: - image_project: cirrus-images - image: family/docker-kvm - platform: linux - cpu: 4 - memory: 16G - nested_virtualization: true - task: name: Vagrant Fedora based test (no VDSO) + environment: + HOME: "/root" + CIRRUS_WORKING_DIR: "/tmp/criu" + + compute_engine_instance: + image_project: cirrus-images + image: family/docker-kvm + platform: linux + cpu: 4 + memory: 16G + nested_virtualization: true + setup_script: | scripts/ci/apt-install make gcc pkg-config git perl-modules iproute2 kmod wget cpu-checker sudo kvm-ok ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto build_script: | make -C scripts/ci vagrant-fedora-no-vdso + +task: + name: CentOS 8 based test + environment: + HOME: "/root" + CIRRUS_WORKING_DIR: "/tmp/criu" + + compute_engine_instance: + image_project: centos-cloud + image: family/centos-8 + platform: linux + cpu: 4 + memory: 8G + + setup_script: | + ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto + yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm dnf-plugins-core + yum config-manager --set-enabled powertools + yum install -y --allowerasing asciidoc gcc git gnutls-devel libaio-devel libasan libcap-devel libnet-devel libnl3-devel libselinux-devel make protobuf-c-devel protobuf-devel python3-devel python3-flake8 python3-PyYAML python3-future python3-protobuf xmlto + alternatives --set python /usr/bin/python3 + systemctl stop sssd + # Even with selinux in permissive mode the selinux tests will be executed + # The Cirrus CI user runs as a service from selinux point of view and is + # much more restricted than a normal shell (system_u:system_r:unconfined_service_t:s0) + # The test case above (vagrant-fedora-no-vdso) should run selinux tests in enforcing mode + setenforce 0 + # netns-nft fails with + # 4: FAIL: netns-nft.c:51: Can't get nft table (errno = 11 (Resource temporarily unavailable)) + mv /usr/sbin/nft /usr/sbin/nft.away + pip3 install junit_xml + + build_script: | + make -C scripts/ci local SKIP_CI_PREP=1 CC=gcc CD_TO_TOP=1 diff --git a/.github/workflows/centos-test.yml b/.github/workflows/centos-test.yml index e14c2460b2..41b1f3a6ea 100644 --- a/.github/workflows/centos-test.yml +++ b/.github/workflows/centos-test.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-20.04 strategy: matrix: - target: [centos7, centos8] + target: [centos7] steps: - uses: actions/checkout@v2 diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 61413cc394..56a4742b8d 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -238,7 +238,7 @@ fi #make -C test/others/exec/ run make -C test/others/make/ run CC="$CC" if [ -n "$TRAVIS" ] || [ -n "$CIRCLECI" ]; then - # GitHub Actions does not provide a real TTY and CRIU will fail with: + # GitHub Actions (and Cirrus CI) does not provide a real TTY and CRIU will fail with: # Error (criu/tty.c:1014): tty: Don't have tty to inherit session from, aborting make -C test/others/shell-job/ run fi From 49b9cff74563b556059b804199da136bab855c3c Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sat, 20 Mar 2021 11:35:32 +0000 Subject: [PATCH 165/204] lib: fix crit-recode fix for Python 2 The recent fix to make Jenkins run crit-recode again broke Python 2 support (because Python 2 based CI was not running). This should fix the Python 2 based test run. Signed-off-by: Adrian Reber --- lib/py/images/images.py | 11 +++++++++-- lib/py/images/pb2dict.py | 11 +++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/lib/py/images/images.py b/lib/py/images/images.py index e4f9ca3d4d..0a9d36f08f 100644 --- a/lib/py/images/images.py +++ b/lib/py/images/images.py @@ -42,6 +42,7 @@ import struct import os import array +import sys from . import magic from . import pb @@ -284,9 +285,15 @@ def dump(self, entries, f): size = len(pb_str) f.write(struct.pack('i', size)) f.write(pb_str) - f.write(base64.decodebytes(str.encode(item['extra']))) + if (sys.version_info > (3, 0)): + f.write(base64.decodebytes(str.encode(item['extra']))) + else: + f.write(base64.decodebytes(item['extra'])) else: - f.write(base64.decodebytes(str.encode(item['extra']))) + if (sys.version_info > (3, 0)): + f.write(base64.decodebytes(str.encode(item['extra']))) + else: + f.write(base64.decodebytes(item['extra'])) def dumps(self, entries): f = io.BytesIO('') diff --git a/lib/py/images/pb2dict.py b/lib/py/images/pb2dict.py index 068d583dc8..cfaff6c7d0 100644 --- a/lib/py/images/pb2dict.py +++ b/lib/py/images/pb2dict.py @@ -3,6 +3,7 @@ import os import quopri import socket +import sys from ipaddress import IPv4Address, IPv6Address, ip_address from google.protobuf.descriptor import FieldDescriptor as FD @@ -246,11 +247,17 @@ def encode_dev(field, value): def encode_base64(value): - return base64.encodebytes(value).decode() + if (sys.version_info > (3, 0)): + return base64.encodebytes(value).decode() + else: + return base64.encodebytes(value) def decode_base64(value): - return base64.decodebytes(str.encode(value)) + if (sys.version_info > (3, 0)): + return base64.decodebytes(str.encode(value)) + else: + return base64.decodebytes(value) def encode_unix(value): From 480605824056e852b72efacdc1c7cee72a4df64d Mon Sep 17 00:00:00 2001 From: Zeyad Yasser Date: Tue, 16 Mar 2021 20:26:14 +0200 Subject: [PATCH 166/204] cr-service: fix CRIU_REQ_TYPE__FEATURE_CHECK RPC request Closes: #1408 CRIU_REQ_TYPE__FEATURE_CHECK was failing, this was caused by two things in handle_feature_check(): 1. setup_opts_from_req() was used and it could be NULL (kerndat_init() is enough for feature checking) 2. resp.success was always set to false Signed-off-by: Zeyad Yasser --- criu/cr-service.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/criu/cr-service.c b/criu/cr-service.c index 56be6bcd37..474f598aca 100644 --- a/criu/cr-service.c +++ b/criu/cr-service.c @@ -1069,8 +1069,7 @@ static int handle_feature_check(int sk, CriuReq * msg) } if (pid == 0) { - /* kerndat_init() is called from setup_opts_from_req() */ - if (setup_opts_from_req(sk, msg->opts)) + if (kerndat_init()) exit(1); setproctitle("feature-check --rpc"); @@ -1104,6 +1103,8 @@ static int handle_feature_check(int sk, CriuReq * msg) if (status != 0) goto out; + return 0; + /* * The child process was not able to send an answer. Tell * the RPC client that something did not work as expected. From 9edf531286e754f2947e3c53f9babfa8e4f22308 Mon Sep 17 00:00:00 2001 From: Bui Quang Minh Date: Sat, 13 Mar 2021 10:22:24 +0700 Subject: [PATCH 167/204] criu: Throw error when parent path is provided but invalid In image dump directory, there are 2 parent symlink error cases: - Parent symlink does not exist - Parent symlink exists but points to invalid target At the moment, 2 cases are handled exactly the same (do full dump). However, while the first case happen when parent path is not provided, the second one is likely user's mistake when provides invalid parent path. So we throw an error in the latter case instead of performing the full dump. Signed-off-by: Bui Quang Minh --- criu/image.c | 31 +++++++++++++++++++++++++++---- criu/include/image.h | 6 ++++++ criu/irmap.c | 6 ++---- criu/page-xfer.c | 24 +++++++++++++++--------- criu/pagemap.c | 6 ++++-- 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/criu/image.c b/criu/image.c index 6ba2ffc7d0..06f7706269 100644 --- a/criu/image.c +++ b/criu/image.c @@ -149,8 +149,7 @@ InventoryEntry *get_parent_inventory(void) InventoryEntry *ie; int dir; - dir = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY); - if (dir == -1) { + if (open_parent(get_service_fd(IMG_FD_OFF), &dir)) { /* * We print the warning below to be notified that we had some * unexpected problem on open. For instance we have a parent @@ -158,10 +157,11 @@ InventoryEntry *get_parent_inventory(void) * when also having no parent directory is an expected case of * first dump iteration. */ - if (errno != ENOENT) - pr_warn("Failed to open parent directory\n"); + pr_warn("Failed to open parent directory\n"); return NULL; } + if (dir < 0) + return NULL; img = open_image_at(dir, CR_FD_INVENTORY, O_RSTR); if (!img) { @@ -561,6 +561,11 @@ int open_image_dir(char *dir, int mode) if (img_streamer_init(dir, mode) < 0) goto err; } else if (opts.img_parent) { + if (faccessat(fd, opts.img_parent, R_OK, 0)) { + pr_perror("Invalid parent image directory provided"); + goto err; + } + ret = symlinkat(opts.img_parent, fd, CR_PARENT_LINK); if (ret < 0 && errno != EEXIST) { pr_perror("Can't link parent snapshot"); @@ -586,6 +591,24 @@ void close_image_dir(void) close_service_fd(IMG_FD_OFF); } +int open_parent(int dfd, int *pfd) +{ + *pfd = -1; + /* Check if the parent symlink exists */ + if (faccessat(dfd, CR_PARENT_LINK, F_OK, AT_SYMLINK_NOFOLLOW) && errno == ENOENT) { + pr_debug("No parent images directory provided\n"); + return 0; + } + + *pfd = openat(dfd, CR_PARENT_LINK, O_RDONLY); + if (*pfd < 0) { + pr_perror("Can't open parent path"); + return -1; + } + + return 0; +} + static unsigned long page_ids = 1; void up_page_ids_base(void) diff --git a/criu/include/image.h b/criu/include/image.h index 62c8d7ba0e..7c45381db3 100644 --- a/criu/include/image.h +++ b/criu/include/image.h @@ -147,6 +147,12 @@ extern off_t img_raw_size(struct cr_img *img); extern int open_image_dir(char *dir, int mode); extern void close_image_dir(void); +/* + * Return -1 -- parent symlink points to invalid target + * Return 0 && pfd < 0 -- parent symlink does not exist + * Return 0 && pfd >= 0 -- opened + */ +extern int open_parent(int dfd, int *pfd); extern struct cr_img *open_image_at(int dfd, int type, unsigned long flags, ...); #define open_image(typ, flags, ...) open_image_at(-1, typ, flags, ##__VA_ARGS__) diff --git a/criu/irmap.c b/criu/irmap.c index 58bc055d56..c9bfdbe223 100644 --- a/criu/irmap.c +++ b/criu/irmap.c @@ -425,12 +425,10 @@ static int open_irmap_cache(struct cr_img **img) close_image(*img); if (dir == AT_FDCWD) { pr_info("Searching irmap cache in parent\n"); - dir = openat(get_service_fd(IMG_FD_OFF), - CR_PARENT_LINK, O_RDONLY); + if (open_parent(get_service_fd(IMG_FD_OFF), &dir)) + return -1; if (dir >= 0) goto in; - if (errno != ENOENT) - return -1; } pr_info("No irmap cache\n"); diff --git a/criu/page-xfer.c b/criu/page-xfer.c index 98e9c6b6e1..34f6a09678 100644 --- a/criu/page-xfer.c +++ b/criu/page-xfer.c @@ -364,10 +364,8 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, unsigned lo return -1; xfer->pi = open_pages_image(O_DUMP, xfer->pmi, &pages_id); - if (!xfer->pi) { - close_image(xfer->pmi); - return -1; - } + if (!xfer->pi) + goto err_pmi; /* * Open page-read for parent images (if it exists). It will @@ -386,14 +384,15 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, unsigned lo if (opts.stream) goto out; - pfd = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY); - if (pfd < 0 && errno == ENOENT) + if (open_parent(get_service_fd(IMG_FD_OFF), &pfd)) + goto err_pi; + if (pfd < 0) goto out; xfer->parent = xmalloc(sizeof(*xfer->parent)); if (!xfer->parent) { close(pfd); - return -1; + goto err_pi; } ret = open_page_read_at(pfd, img_id, xfer->parent, pr_flags); @@ -412,6 +411,12 @@ static int open_page_local_xfer(struct page_xfer *xfer, int fd_type, unsigned lo xfer->write_pages = write_pages_loc; xfer->close = close_page_xfer; return 0; + +err_pi: + close_image(xfer->pi); +err_pmi: + close_image(xfer->pmi); + return -1; } int open_page_xfer(struct page_xfer *xfer, int fd_type, unsigned long img_id) @@ -936,8 +941,9 @@ int check_parent_local_xfer(int fd_type, unsigned long img_id) if (opts.stream) return 0; - pfd = openat(get_service_fd(IMG_FD_OFF), CR_PARENT_LINK, O_RDONLY); - if (pfd < 0 && errno == ENOENT) + if (open_parent(get_service_fd(IMG_FD_OFF), &pfd)) + return -1; + if (pfd < 0) return 0; snprintf(path, sizeof(path), imgset_template[fd_type].fmt, img_id); diff --git a/criu/pagemap.c b/criu/pagemap.c index abcdcdfd5e..1d849a1b99 100644 --- a/criu/pagemap.c +++ b/criu/pagemap.c @@ -661,8 +661,9 @@ static int try_open_parent(int dfd, unsigned long id, struct page_read *pr, int if (opts.stream) goto out; - pfd = openat(dfd, CR_PARENT_LINK, O_RDONLY); - if (pfd < 0 && errno == ENOENT) + if (open_parent(dfd, &pfd)) + goto err; + if (pfd < 0) goto out; parent = xmalloc(sizeof(*parent)); @@ -687,6 +688,7 @@ static int try_open_parent(int dfd, unsigned long id, struct page_read *pr, int xfree(parent); err_cl: close(pfd); +err: return -1; } From 840dc0b4db3970eaf459bd535943357afba9384b Mon Sep 17 00:00:00 2001 From: Bui Quang Minh Date: Tue, 30 Mar 2021 21:06:19 +0700 Subject: [PATCH 168/204] criu: Replace faccessat with fstatat when using AT_SYMLINK_NOFOLLOW flag Currently, alpine musl libc library returns Invalid argument error (EINVAL) when calling faccessat with AT_SYMLINK_NOFOLLOW flag. Fix this by using fstatat instead. Signed-off-by: Bui Quang Minh --- criu/image.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/criu/image.c b/criu/image.c index 06f7706269..84101b610f 100644 --- a/criu/image.c +++ b/criu/image.c @@ -593,9 +593,11 @@ void close_image_dir(void) int open_parent(int dfd, int *pfd) { + struct stat st; + *pfd = -1; /* Check if the parent symlink exists */ - if (faccessat(dfd, CR_PARENT_LINK, F_OK, AT_SYMLINK_NOFOLLOW) && errno == ENOENT) { + if (fstatat(dfd, CR_PARENT_LINK, &st, AT_SYMLINK_NOFOLLOW) && errno == ENOENT) { pr_debug("No parent images directory provided\n"); return 0; } From f9616e9176d92a54db1d3747c89aee7af53a6d1e Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 10 Mar 2021 17:14:41 +0000 Subject: [PATCH 169/204] lib: correctly handle stdin/stdout (Python 3) This changes stdin to be opened as binary if the input is not a tty. This changes stdout to be opened as binary if encoding or if the output is not a tty. Signed-off-by: Adrian Reber --- lib/py/cli.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/lib/py/cli.py b/lib/py/cli.py index df96729e2e..1d8b8515fc 100755 --- a/lib/py/cli.py +++ b/lib/py/cli.py @@ -11,14 +11,28 @@ def inf(opts): if opts['in']: return open(opts['in'], 'rb') else: - return sys.stdin + if (sys.version_info < (3, 0)): + return sys.stdin + if sys.stdin.isatty(): + # If we are reading from a terminal (not a pipe) we want text input and not binary + return sys.stdin + return sys.stdin.buffer -def outf(opts): +def outf(opts, decode): + # Decode means from protobuf to JSON. + # Use text when writing to JSON else use binaray mode if opts['out']: - return open(opts['out'], 'wb+') + mode = 'wb+' + if decode: + mode = 'w+' + return open(opts['out'], mode) else: - return sys.stdout + if (sys.version_info < (3, 0)): + return sys.stdout + if decode: + return sys.stdout + return sys.stdout.buffer def dinf(opts, name): @@ -39,7 +53,7 @@ def decode(opts): if opts['pretty']: indent = 4 - f = outf(opts) + f = outf(opts, True) json.dump(img, f, indent=indent) if f == sys.stdout: f.write("\n") @@ -47,7 +61,7 @@ def decode(opts): def encode(opts): img = json.load(inf(opts)) - pycriu.images.dump(img, outf(opts)) + pycriu.images.dump(img, outf(opts, False)) def info(opts): From 35a4761ab7419b5536b85a52082699ffab492d19 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 15 Mar 2021 13:57:38 +0000 Subject: [PATCH 170/204] lib: print nice error if crit gets wrong input Signed-off-by: Adrian Reber --- lib/py/cli.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/py/cli.py b/lib/py/cli.py index 1d8b8515fc..cb125aab87 100755 --- a/lib/py/cli.py +++ b/lib/py/cli.py @@ -60,7 +60,13 @@ def decode(opts): def encode(opts): - img = json.load(inf(opts)) + try: + img = json.load(inf(opts)) + except UnicodeDecodeError: + print("Cannot read JSON.\n"\ + "Maybe you are feeding me an image with protobuf data? "\ + "Encode expects JSON input.", file=sys.stderr) + sys.exit(1) pycriu.images.dump(img, outf(opts, False)) From e65a56a1e50b72963ce2c1b45818defad851d0a7 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 23 Mar 2021 08:48:03 +0000 Subject: [PATCH 171/204] lib: also handle extra pipe data correctly CI sometimes errors out encoding/decoding extra pipe data. This should fix extra pipe data for Python 3 and still keep it working on Python 2. Signed-off-by: Adrian Reber --- lib/py/images/images.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/py/images/images.py b/lib/py/images/images.py index 0a9d36f08f..956932e03d 100644 --- a/lib/py/images/images.py +++ b/lib/py/images/images.py @@ -311,10 +311,13 @@ class pipes_data_extra_handler: def load(self, f, pload): size = pload.bytes data = f.read(size) - return base64.encodebytes(data) + return base64.encodebytes(data).decode() def dump(self, extra, f, pload): - data = base64.decodebytes(extra) + if (sys.version_info > (3, 0)): + data = base64.decodebytes(str.encode(extra)) + else: + data = base64.decodebytes(extra) f.write(data) def skip(self, f, pload): @@ -326,10 +329,13 @@ class sk_queues_extra_handler: def load(self, f, pload): size = pload.length data = f.read(size) - return base64.encodebytes(data) + return base64.encodebytes(data).decode() def dump(self, extra, f, _unused): - data = base64.decodebytes(extra) + if (sys.version_info > (3, 0)): + data = base64.decodebytes(str.encode(extra)) + else: + data = base64.decodebytes(extra) f.write(data) def skip(self, f, pload): From 7accc44546a7e41d9107ba2733e8f2f4b851f5fe Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 15 Mar 2021 14:03:25 +0000 Subject: [PATCH 172/204] test: fix crit test and extend it This fixes the others/crit test to work again and extends it to make sure all possible input and output options are correctly handled by crit. Signed-off-by: Adrian Reber --- Makefile | 1 + test/others/crit/test.sh | 70 ++++++++++++++++++++++++++++++++++++---- test/others/env.sh | 11 ++++++- 3 files changed, 75 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 6b7972efe4..3bdfb91bc0 100644 --- a/Makefile +++ b/Makefile @@ -412,6 +412,7 @@ lint: flake8 --config=scripts/flake8.cfg lib/py/images/pb2dict.py shellcheck scripts/*.sh shellcheck scripts/ci/*.sh scripts/ci/apt-install + shellcheck test/others/crit/*.sh codecov: SHELL := $(shell which bash) codecov: diff --git a/test/others/crit/test.sh b/test/others/crit/test.sh index a85b4c3b2d..9d30575c48 100755 --- a/test/others/crit/test.sh +++ b/test/others/crit/test.sh @@ -1,8 +1,14 @@ +#!/bin/bash +# shellcheck disable=SC1091,SC2002 + +set -x + source ../env.sh images_list="" function _exit { + # shellcheck disable=SC2181 if [ $? -ne 0 ]; then echo "FAIL" exit 1 @@ -13,37 +19,89 @@ function gen_imgs { setsid ./loop.sh < /dev/null &> /dev/null & PID=$! $CRIU dump -v4 -o dump.log -D ./ -t $PID + # shellcheck disable=SC2181 if [ $? -ne 0 ]; then kill -9 $PID _exit 1 fi - images_list=$(ls -1 *.img) + images_list=$(ls -1 ./*.img) if [ -z "$images_list" ]; then echo "Failed to generate images" _exit 1 fi } -function run_test { +function run_test1 { for x in $images_list do echo "=== $x" - if [[ $x == pages* ]]; then + if [[ $x == *pages* ]]; then echo "skip" continue fi echo " -- to json" - $CRIT decode -o "$x"".json" --pretty < $x || _exit $? + $CRIT decode -o "$x"".json" --pretty < "$x" || _exit $? echo " -- to img" $CRIT encode -i "$x"".json" > "$x"".json.img" || _exit $? echo " -- cmp" - cmp $x "$x"".json.img" || _exit $? + cmp "$x" "$x"".json.img" || _exit $? echo "=== done" done } + +function run_test2 { + mapfile -t array <<< "$images_list" + + PROTO_IN=${array[0]} + JSON_IN=$(mktemp -p ./ tmp.XXXXXXXXXX.json) + OUT=$(mktemp -p ./ tmp.XXXXXXXXXX.log) + + # prepare + ${CRIT} decode -i "${PROTO_IN}" -o "${JSON_IN}" + + # proto in - json out decode + cat "${PROTO_IN}" | ${CRIT} decode || _exit 1 + cat "${PROTO_IN}" | ${CRIT} decode -o "${OUT}" || _exit 1 + cat "${PROTO_IN}" | ${CRIT} decode > "${OUT}" || _exit 1 + ${CRIT} decode -i "${PROTO_IN}" || _exit 1 + ${CRIT} decode -i "${PROTO_IN}" -o "${OUT}" || _exit 1 + ${CRIT} decode -i "${PROTO_IN}" > "${OUT}" || _exit 1 + ${CRIT} decode < "${PROTO_IN}" || _exit 1 + ${CRIT} decode -o "${OUT}" < "${PROTO_IN}" || _exit 1 + ${CRIT} decode < "${PROTO_IN}" > "${OUT}" || _exit 1 + + # proto in - json out encode -> should fail + cat "${PROTO_IN}" | ${CRIT} encode || true + cat "${PROTO_IN}" | ${CRIT} encode -o "${OUT}" || true + cat "${PROTO_IN}" | ${CRIT} encode > "${OUT}" || true + ${CRIT} encode -i "${PROTO_IN}" || true + ${CRIT} encode -i "${PROTO_IN}" -o "${OUT}" || true + ${CRIT} encode -i "${PROTO_IN}" > "${OUT}" || true + + # json in - proto out encode + cat "${JSON_IN}" | ${CRIT} encode || _exit 1 + cat "${JSON_IN}" | ${CRIT} encode -o "${OUT}" || _exit 1 + cat "${JSON_IN}" | ${CRIT} encode > "${OUT}" || _exit 1 + ${CRIT} encode -i "${JSON_IN}" || _exit 1 + ${CRIT} encode -i "${JSON_IN}" -o "${OUT}" || _exit 1 + ${CRIT} encode -i "${JSON_IN}" > "${OUT}" || _exit 1 + ${CRIT} encode < "${JSON_IN}" || _exit 1 + ${CRIT} encode -o "${OUT}" < "${JSON_IN}" || _exit 1 + ${CRIT} encode < "${JSON_IN}" > "${OUT}" || _exit 1 + + # json in - proto out decode -> should fail + cat "${JSON_IN}" | ${CRIT} decode || true + cat "${JSON_IN}" | ${CRIT} decode -o "${OUT}" || true + cat "${JSON_IN}" | ${CRIT} decode > "${OUT}" || true + ${CRIT} decode -i "${JSON_IN}" || true + ${CRIT} decode -i "${JSON_IN}" -o "${OUT}" || true + ${CRIT} decode -i "${JSON_IN}" > "${OUT}" || true +} + gen_imgs -run_test +run_test1 +run_test2 diff --git a/test/others/env.sh b/test/others/env.sh index 73369ad1bd..b514e87d9e 100755 --- a/test/others/env.sh +++ b/test/others/env.sh @@ -2,7 +2,16 @@ CRIU=$(readlink -f `dirname ${BASH_SOURCE[0]}`/../../criu/criu) criu=$CRIU -CRIT=$(readlink -f `dirname ${BASH_SOURCE[0]}`/../../crit/crit) +if [ $(which python3) ]; then + PYTHON=python3 +elif [ $(which python2) ]; then + PYTHON=python2 +else + echo "FAIL: Neither python3 nor python2" + exit 1 +fi +#export PYTHON +CRIT=$(readlink -f `dirname ${BASH_SOURCE[0]}`/../../crit/crit-"${PYTHON}") crit=$CRIT CRIU_COREDUMP=$(readlink -f `dirname ${BASH_SOURCE[0]}`/../../criu-coredump/criu-coredump) criu_coredump=$CRIU_COREDUMP From 38a9cbe7af3d9efa021b505aa0580cb352cad89c Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 15 Mar 2021 14:06:18 +0000 Subject: [PATCH 173/204] ci: enable crit tests in CI Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 56a4742b8d..f1ed6bcfce 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -268,6 +268,9 @@ ip net add test ./test/zdtm.py run -t zdtm/static/env00 -t zdtm/transition/fork -t zdtm/static/ghost_holes00 -k always ./test/crit-recode.py +# more crit testing +make -C test/others/crit run + # libcriu testing make -C test/others/libcriu run From b98bbda8e588fec6b6a3bd370ab56749cfc73019 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 8 May 2020 11:36:57 +0000 Subject: [PATCH 174/204] images: re-license as Expat license (so-called MIT) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This changes the license of all files in the images/ directory from GPLv2 to the Expat license (so-called MIT). According to git the files have been authored by: Abhishek Dubey Adrian Reber Alexander Mikhalitsyn Alice Frosi Andrei Vagin (Andrew Vagin, Andrey Vagin) Cyrill Gorcunov Dengguangxing Dmitry Safonov Guoyun Sun Kirill Tkhai Kir Kolyshkin Laurent Dufour Michael Holzheu Michał Cłapiński Mike Rapoport Nicolas Viennot Nikita Spiridonov Pavel Emelianov (Pavel Emelyanov) Pavel Tikhomirov Radostin Stoyanov rbruno@gsd.inesc-id.pt Sebastian Pipping Stanislav Kinsburskiy Tycho Andersen Valeriy Vdovin The Expat license (so-called MIT) can be found here: https://opensource.org/licenses/MIT According to that link the correct SPDX short identifier is 'MIT'. https://spdx.org/licenses/MIT.html Signed-off-by: Adrian Reber --- README.md | 3 +++ images/LICENSE | 19 +++++++++++++++++++ images/autofs.proto | 2 ++ images/binfmt-misc.proto | 2 ++ images/bpfmap-data.proto | 2 ++ images/bpfmap-file.proto | 2 ++ images/cgroup.proto | 2 ++ images/core-aarch64.proto | 2 ++ images/core-arm.proto | 2 ++ images/core-mips.proto | 2 ++ images/core-ppc64.proto | 2 ++ images/core-s390.proto | 2 ++ images/core-x86.proto | 2 ++ images/core.proto | 2 ++ images/cpuinfo.proto | 2 ++ images/creds.proto | 2 ++ images/eventfd.proto | 2 ++ images/eventpoll.proto | 2 ++ images/ext-file.proto | 2 ++ images/fdinfo.proto | 2 ++ images/fh.proto | 2 ++ images/fifo.proto | 2 ++ images/file-lock.proto | 2 ++ images/fown.proto | 2 ++ images/fs.proto | 2 ++ images/fsnotify.proto | 2 ++ images/ghost-file.proto | 2 ++ images/img-streamer.proto | 2 ++ images/inventory.proto | 2 ++ images/ipc-desc.proto | 2 ++ images/ipc-msg.proto | 2 ++ images/ipc-sem.proto | 2 ++ images/ipc-shm.proto | 2 ++ images/ipc-var.proto | 2 ++ images/macvlan.proto | 2 ++ images/memfd.proto | 2 ++ images/mm.proto | 2 ++ images/mnt.proto | 2 ++ images/netdev.proto | 2 ++ images/ns.proto | 2 ++ images/opts.proto | 2 ++ images/packet-sock.proto | 2 ++ images/pagemap.proto | 2 ++ images/pidns.proto | 2 ++ images/pipe-data.proto | 2 ++ images/pipe.proto | 2 ++ images/pstree.proto | 2 ++ images/regfile.proto | 2 ++ images/remap-file-path.proto | 2 ++ images/rlimit.proto | 2 ++ images/rpc.proto | 2 ++ images/sa.proto | 2 ++ images/seccomp.proto | 2 ++ images/siginfo.proto | 2 ++ images/signalfd.proto | 2 ++ images/sit.proto | 2 ++ images/sk-inet.proto | 2 ++ images/sk-netlink.proto | 2 ++ images/sk-opts.proto | 2 ++ images/sk-packet.proto | 2 ++ images/sk-unix.proto | 2 ++ images/stats.proto | 2 ++ images/sysctl.proto | 2 ++ images/tcp-stream.proto | 2 ++ images/time.proto | 2 ++ images/timens.proto | 2 ++ images/timer.proto | 2 ++ images/timerfd.proto | 2 ++ images/tty.proto | 2 ++ images/tun.proto | 2 ++ images/userns.proto | 2 ++ images/utsns.proto | 2 ++ images/vma.proto | 2 ++ 73 files changed, 164 insertions(+) create mode 100644 images/LICENSE diff --git a/README.md b/README.md index ee8987f3c7..fd86b2c159 100644 --- a/README.md +++ b/README.md @@ -65,3 +65,6 @@ itself, and we have it available as the [libsoccr library](https://criu.org/Libs ## Licence The project is licensed under GPLv2 (though files sitting in the lib/ directory are LGPLv2.1). + +All files in the images/ directory are licensed under the Expat license (so-called MIT). +See the images/LICENSE file. diff --git a/images/LICENSE b/images/LICENSE new file mode 100644 index 0000000000..3c6395a105 --- /dev/null +++ b/images/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2020 The CRIU developers + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/images/autofs.proto b/images/autofs.proto index 2146ca89f0..5c8c216c84 100644 --- a/images/autofs.proto +++ b/images/autofs.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message autofs_entry { diff --git a/images/binfmt-misc.proto b/images/binfmt-misc.proto index 82a86c8c94..a48d8724c5 100644 --- a/images/binfmt-misc.proto +++ b/images/binfmt-misc.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message binfmt_misc_entry { diff --git a/images/bpfmap-data.proto b/images/bpfmap-data.proto index dc3b0db017..b9502bb452 100644 --- a/images/bpfmap-data.proto +++ b/images/bpfmap-data.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message bpfmap_data_entry { diff --git a/images/bpfmap-file.proto b/images/bpfmap-file.proto index 6560bb646e..34a6c1dd29 100644 --- a/images/bpfmap-file.proto +++ b/images/bpfmap-file.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/cgroup.proto b/images/cgroup.proto index b8a545e3ce..ee03541240 100644 --- a/images/cgroup.proto +++ b/images/cgroup.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message cgroup_perms { diff --git a/images/core-aarch64.proto b/images/core-aarch64.proto index 83fdd64372..3356e6b757 100644 --- a/images/core-aarch64.proto +++ b/images/core-aarch64.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/core-arm.proto b/images/core-arm.proto index 3004346bb9..f9c9e80cb6 100644 --- a/images/core-arm.proto +++ b/images/core-arm.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/core-mips.proto b/images/core-mips.proto index 6391b1e86f..ec06d69511 100755 --- a/images/core-mips.proto +++ b/images/core-mips.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/core-ppc64.proto b/images/core-ppc64.proto index aca1c2faee..6a27f90128 100644 --- a/images/core-ppc64.proto +++ b/images/core-ppc64.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/core-s390.proto b/images/core-s390.proto index 497c73b206..44130f2060 100644 --- a/images/core-s390.proto +++ b/images/core-s390.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/core-x86.proto b/images/core-x86.proto index 2ed2ad35d9..ee7be8ff11 100644 --- a/images/core-x86.proto +++ b/images/core-x86.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/core.proto b/images/core.proto index 9e9e39388f..b713119f27 100644 --- a/images/core.proto +++ b/images/core.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "core-x86.proto"; diff --git a/images/cpuinfo.proto b/images/cpuinfo.proto index 8ee629c2c9..15860a90c5 100644 --- a/images/cpuinfo.proto +++ b/images/cpuinfo.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message cpuinfo_x86_entry { diff --git a/images/creds.proto b/images/creds.proto index 23b84c7e50..0007fb46db 100644 --- a/images/creds.proto +++ b/images/creds.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message creds_entry { diff --git a/images/eventfd.proto b/images/eventfd.proto index ff9ced3934..225462f763 100644 --- a/images/eventfd.proto +++ b/images/eventfd.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "fown.proto"; diff --git a/images/eventpoll.proto b/images/eventpoll.proto index 4a8d1b834e..0f3e8a870b 100644 --- a/images/eventpoll.proto +++ b/images/eventpoll.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "fown.proto"; diff --git a/images/ext-file.proto b/images/ext-file.proto index f820ffb07a..8b4f825681 100644 --- a/images/ext-file.proto +++ b/images/ext-file.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "fown.proto"; diff --git a/images/fdinfo.proto b/images/fdinfo.proto index f5e18954bb..88f1c11860 100644 --- a/images/fdinfo.proto +++ b/images/fdinfo.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "regfile.proto"; diff --git a/images/fh.proto b/images/fh.proto index 2da7e9deb0..7a2ce484ba 100644 --- a/images/fh.proto +++ b/images/fh.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/fifo.proto b/images/fifo.proto index f5b3283ffa..ae6f48162a 100644 --- a/images/fifo.proto +++ b/images/fifo.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message fifo_entry { diff --git a/images/file-lock.proto b/images/file-lock.proto index 5dd8847cc3..dcf3d871ca 100644 --- a/images/file-lock.proto +++ b/images/file-lock.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message file_lock_entry { diff --git a/images/fown.proto b/images/fown.proto index 9956b98656..b2e20b6572 100644 --- a/images/fown.proto +++ b/images/fown.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message fown_entry { diff --git a/images/fs.proto b/images/fs.proto index 5b940a1c1a..158501ac9d 100644 --- a/images/fs.proto +++ b/images/fs.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message fs_entry { diff --git a/images/fsnotify.proto b/images/fsnotify.proto index 399a449a02..df6a667f86 100644 --- a/images/fsnotify.proto +++ b/images/fsnotify.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/ghost-file.proto b/images/ghost-file.proto index 0576089fdd..9ecee41d24 100644 --- a/images/ghost-file.proto +++ b/images/ghost-file.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/img-streamer.proto b/images/img-streamer.proto index d1bd4cc191..48a3a93b0e 100644 --- a/images/img-streamer.proto +++ b/images/img-streamer.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; // This message is sent from CRIU to the streamer. diff --git a/images/inventory.proto b/images/inventory.proto index d7d0622c40..56e85a80a9 100644 --- a/images/inventory.proto +++ b/images/inventory.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "core.proto"; diff --git a/images/ipc-desc.proto b/images/ipc-desc.proto index b400bd7d2a..8b4c7f5baa 100644 --- a/images/ipc-desc.proto +++ b/images/ipc-desc.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message ipc_desc_entry { diff --git a/images/ipc-msg.proto b/images/ipc-msg.proto index 5260ea8626..5b3103182f 100644 --- a/images/ipc-msg.proto +++ b/images/ipc-msg.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "ipc-desc.proto"; diff --git a/images/ipc-sem.proto b/images/ipc-sem.proto index bffb581aec..71a2beb948 100644 --- a/images/ipc-sem.proto +++ b/images/ipc-sem.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "ipc-desc.proto"; diff --git a/images/ipc-shm.proto b/images/ipc-shm.proto index 31e172eb8e..7865dad8dd 100644 --- a/images/ipc-shm.proto +++ b/images/ipc-shm.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "ipc-desc.proto"; diff --git a/images/ipc-var.proto b/images/ipc-var.proto index f46fcdeebd..a5e2df9dec 100644 --- a/images/ipc-var.proto +++ b/images/ipc-var.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message ipc_var_entry { diff --git a/images/macvlan.proto b/images/macvlan.proto index 0ca2652f03..6f78076d8e 100644 --- a/images/macvlan.proto +++ b/images/macvlan.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message macvlan_link_entry { diff --git a/images/memfd.proto b/images/memfd.proto index ad5373d10a..a944f145d7 100644 --- a/images/memfd.proto +++ b/images/memfd.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/mm.proto b/images/mm.proto index e0f14c62f6..b37668c4b3 100644 --- a/images/mm.proto +++ b/images/mm.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/mnt.proto b/images/mnt.proto index 8983395aea..4abb7d1a95 100644 --- a/images/mnt.proto +++ b/images/mnt.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/netdev.proto b/images/netdev.proto index ae9c995316..748fd02004 100644 --- a/images/netdev.proto +++ b/images/netdev.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "macvlan.proto"; diff --git a/images/ns.proto b/images/ns.proto index 5ff0001652..19ec641f62 100644 --- a/images/ns.proto +++ b/images/ns.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message ns_file_entry { diff --git a/images/opts.proto b/images/opts.proto index 70c7fd481f..95304a8c60 100644 --- a/images/opts.proto +++ b/images/opts.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "google/protobuf/descriptor.proto"; diff --git a/images/packet-sock.proto b/images/packet-sock.proto index 25875b4702..d4b38cf154 100644 --- a/images/packet-sock.proto +++ b/images/packet-sock.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/pagemap.proto b/images/pagemap.proto index 42ed5ebb9c..e6d341b0f6 100644 --- a/images/pagemap.proto +++ b/images/pagemap.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/pidns.proto b/images/pidns.proto index 7ff0497494..f7e92e3ecd 100644 --- a/images/pidns.proto +++ b/images/pidns.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message pidns_entry { diff --git a/images/pipe-data.proto b/images/pipe-data.proto index 78d53a8902..040479e7cb 100644 --- a/images/pipe-data.proto +++ b/images/pipe-data.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message pipe_data_entry { diff --git a/images/pipe.proto b/images/pipe.proto index a9a213b90b..2c0360e852 100644 --- a/images/pipe.proto +++ b/images/pipe.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/pstree.proto b/images/pstree.proto index 23e88aa74f..fca284cb73 100644 --- a/images/pstree.proto +++ b/images/pstree.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message pstree_entry { diff --git a/images/regfile.proto b/images/regfile.proto index 49884ddc9b..bf22d2026d 100644 --- a/images/regfile.proto +++ b/images/regfile.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/remap-file-path.proto b/images/remap-file-path.proto index 3cc78a25e7..8635370c0c 100644 --- a/images/remap-file-path.proto +++ b/images/remap-file-path.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; enum remap_type { diff --git a/images/rlimit.proto b/images/rlimit.proto index 773a8df9ce..3a3aeda306 100644 --- a/images/rlimit.proto +++ b/images/rlimit.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message rlimit_entry { diff --git a/images/rpc.proto b/images/rpc.proto index df1b5aed2a..c968cc9918 100644 --- a/images/rpc.proto +++ b/images/rpc.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message criu_page_server_info { diff --git a/images/sa.proto b/images/sa.proto index 07fd4ffd3f..07f71c3a03 100644 --- a/images/sa.proto +++ b/images/sa.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/seccomp.proto b/images/seccomp.proto index 177e5fd4a5..e56cea3a1d 100644 --- a/images/seccomp.proto +++ b/images/seccomp.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message seccomp_filter { diff --git a/images/siginfo.proto b/images/siginfo.proto index e0d141e6c6..6e696c7fd8 100644 --- a/images/siginfo.proto +++ b/images/siginfo.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message siginfo_entry { diff --git a/images/signalfd.proto b/images/signalfd.proto index 31d0d9f006..83546ae218 100644 --- a/images/signalfd.proto +++ b/images/signalfd.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/sit.proto b/images/sit.proto index 7ca91ccd0e..5396458581 100644 --- a/images/sit.proto +++ b/images/sit.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/sk-inet.proto b/images/sk-inet.proto index 75d565dcdd..594e29c662 100644 --- a/images/sk-inet.proto +++ b/images/sk-inet.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/sk-netlink.proto b/images/sk-netlink.proto index 97fa445860..cfcc88daad 100644 --- a/images/sk-netlink.proto +++ b/images/sk-netlink.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/sk-opts.proto b/images/sk-opts.proto index 5bdc5063ff..2377f6b629 100644 --- a/images/sk-opts.proto +++ b/images/sk-opts.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message sk_opts_entry { diff --git a/images/sk-packet.proto b/images/sk-packet.proto index e15dd382a5..b60a8870a7 100644 --- a/images/sk-packet.proto +++ b/images/sk-packet.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message scm_entry { diff --git a/images/sk-unix.proto b/images/sk-unix.proto index 2a3a7cc320..8ddbccde00 100644 --- a/images/sk-unix.proto +++ b/images/sk-unix.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/stats.proto b/images/stats.proto index 68d2f1bbbb..64e46181da 100644 --- a/images/stats.proto +++ b/images/stats.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; // This one contains statistics about dump/restore process diff --git a/images/sysctl.proto b/images/sysctl.proto index 4ecdf27011..0922b87ab0 100644 --- a/images/sysctl.proto +++ b/images/sysctl.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; enum SysctlType { diff --git a/images/tcp-stream.proto b/images/tcp-stream.proto index 1740783052..c2244ba3bf 100644 --- a/images/tcp-stream.proto +++ b/images/tcp-stream.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/time.proto b/images/time.proto index 4bb2b94596..5e5e7eee47 100644 --- a/images/time.proto +++ b/images/time.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message timeval { diff --git a/images/timens.proto b/images/timens.proto index a8272609b0..79097a18d4 100644 --- a/images/timens.proto +++ b/images/timens.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message timespec { diff --git a/images/timer.proto b/images/timer.proto index a254a6f809..4eb5452b35 100644 --- a/images/timer.proto +++ b/images/timer.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message itimer_entry { diff --git a/images/timerfd.proto b/images/timerfd.proto index 2432815492..0bdf125388 100644 --- a/images/timerfd.proto +++ b/images/timerfd.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/tty.proto b/images/tty.proto index ed664ef513..14bc543ece 100644 --- a/images/tty.proto +++ b/images/tty.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/tun.proto b/images/tun.proto index b70c9ed67d..ad61037db1 100644 --- a/images/tun.proto +++ b/images/tun.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; diff --git a/images/userns.proto b/images/userns.proto index 16be6b161d..3a23cbbf87 100644 --- a/images/userns.proto +++ b/images/userns.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message uid_gid_extent { diff --git a/images/utsns.proto b/images/utsns.proto index a29aea1c27..efc689fa55 100644 --- a/images/utsns.proto +++ b/images/utsns.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; message utsns_entry { diff --git a/images/vma.proto b/images/vma.proto index 7085f4237e..0c07d51c6b 100644 --- a/images/vma.proto +++ b/images/vma.proto @@ -1,3 +1,5 @@ +// SPDX-License-Identifier: MIT + syntax = "proto2"; import "opts.proto"; From 9d7353af58407e84b6baab2b79a133f5c8d7b10a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Mon, 12 Apr 2021 13:20:27 +0000 Subject: [PATCH 175/204] Makefile: add show-version command Signed-off-by: Adrian Reber --- Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3bdfb91bc0..28c23cf673 100644 --- a/Makefile +++ b/Makefile @@ -202,7 +202,7 @@ criu-deps += include/common/asm # # Configure variables. export CONFIG_HEADER := include/common/config.h -ifeq ($(filter tags etags cscope clean mrproper,$(MAKECMDGOALS)),) +ifeq ($(filter tags etags cscope clean mrproper show-version help,$(MAKECMDGOALS)),) include Makefile.config else # To clean all files, enable make/build options here @@ -349,6 +349,10 @@ criu-$(tar-name).tar.bz2: dist tar: criu-$(tar-name).tar.bz2 ; .PHONY: dist tar +show-version: + @echo $(head-name) +.PHONY: show-version + TAGS_FILES_REGEXP := . -name '*.[hcS]' ! -path './.*' \( ! -path './test/*' -o -path './test/zdtm/lib/*' \) tags: $(call msg-gen, $@) @@ -402,6 +406,7 @@ help: @echo ' cscope - Generate cscope database' @echo ' test - Run zdtm test-suite' @echo ' gcov - Make code coverage report' + @echo ' show-version - Show current CRIU version' .PHONY: help lint: From 850e63f21b1cc7aafc09db1edcb7bac077dbb12a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Sat, 10 Apr 2021 17:45:42 +0000 Subject: [PATCH 176/204] Try packit 3 Signed-off-by: Adrian Reber --- .packit.yaml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 .packit.yaml diff --git a/.packit.yaml b/.packit.yaml new file mode 100644 index 0000000000..64e0c64e94 --- /dev/null +++ b/.packit.yaml @@ -0,0 +1,26 @@ +# See the documentation for more information: +# https://packit.dev/docs/configuration/ + +specfile_path: criu.spec + +# add or remove files that should be synced +synced_files: + - criu.spec + - .packit.yaml + - criu-tmpfiles.conf + +# name in upstream package repository/registry (e.g. in PyPI) +upstream_package_name: criu +# downstream (Fedora) RPM package name +downstream_package_name: criu +actions: + post-upstream-clone: + - "wget https://src.fedoraproject.org/rpms/criu/raw/rawhide/f/criu.spec -O criu.spec" + - "wget https://src.fedoraproject.org/rpms/criu/raw/rawhide/f/criu-tmpfiles.conf -O criu-tmpfiles.conf" + +jobs: +- job: copr_build + trigger: pull_request + metadata: + targets: + - fedora-all From b3a87639c7d64556755d796b000103634e5502d9 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 11:53:00 +0000 Subject: [PATCH 177/204] fmf definitions Signed-off-by: Adrian Reber --- .fmf/all.fmf | 1 + .fmf/version | 1 + scripts/ci/ci.fmf | 9 +++++++++ test/all.fmf | 6 ++++++ 4 files changed, 17 insertions(+) create mode 100644 .fmf/all.fmf create mode 100644 .fmf/version create mode 100644 scripts/ci/ci.fmf create mode 100644 test/all.fmf diff --git a/.fmf/all.fmf b/.fmf/all.fmf new file mode 100644 index 0000000000..e61ef7b965 --- /dev/null +++ b/.fmf/all.fmf @@ -0,0 +1 @@ +aa diff --git a/.fmf/version b/.fmf/version new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/.fmf/version @@ -0,0 +1 @@ +1 diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf new file mode 100644 index 0000000000..f405d9da8b --- /dev/null +++ b/scripts/ci/ci.fmf @@ -0,0 +1,9 @@ +summary: + Run CI test suite +require: + - git + - libvirt-python3 + - make + - python3 +test: ./run-ci-tests.sh +duration: 60m diff --git a/test/all.fmf b/test/all.fmf new file mode 100644 index 0000000000..2bce34a64a --- /dev/null +++ b/test/all.fmf @@ -0,0 +1,6 @@ +summary: + Run all tests +discover: + how: fmf +execute: + how: tmt From 4550c2768aa26452890be1269f3a635522d09f16 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 12:02:01 +0000 Subject: [PATCH 178/204] tests not copr_build Signed-off-by: Adrian Reber --- .packit.yaml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.packit.yaml b/.packit.yaml index 64e0c64e94..ab6d0be37d 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -24,3 +24,8 @@ jobs: metadata: targets: - fedora-all +- job: tests + trigger: pull_request + metadata: + targets: + - fedora-all From f96459cef514a9dbedeee116c19f09e3974724a4 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 14:39:55 +0000 Subject: [PATCH 179/204] ci.fmf Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index f405d9da8b..89a676bf61 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -2,8 +2,7 @@ summary: Run CI test suite require: - git - - libvirt-python3 - make - python3 -test: ./run-ci-tests.sh +test: SKIP_CI_PREP=1 ./run-ci-tests.sh duration: 60m From fbed4e7e76f4967bac1db010f168a29e1198400c Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 14:58:42 +0000 Subject: [PATCH 180/204] arch64 and x86_64 Signed-off-by: Adrian Reber --- .packit.yaml | 6 ++++-- scripts/ci/ci.fmf | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.packit.yaml b/.packit.yaml index ab6d0be37d..692c85e5a8 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -23,9 +23,11 @@ jobs: trigger: pull_request metadata: targets: - - fedora-all + - fedora-all-x86_64 + - fedora-all-aarch64 - job: tests trigger: pull_request metadata: targets: - - fedora-all + - fedora-all-x86_64 + - fedora-all-aarch64 diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 89a676bf61..89bcee5243 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: SKIP_CI_PREP=1 ./run-ci-tests.sh +test: SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From 06df9790f9bc1653f016e7aaf89a92e56520073d Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 15:37:11 +0000 Subject: [PATCH 181/204] install dependencies Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 89bcee5243..2eb27de90a 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: ./prepare-for-fedora-rawhide.sh; SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From be84ef4183e83c33b8a937d3e02eea35f28fabb7 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 16:49:12 +0000 Subject: [PATCH 182/204] cd_to_top Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 2eb27de90a..c32e792f47 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: ./prepare-for-fedora-rawhide.sh; SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: ./prepare-for-fedora-rawhide.sh; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From 955920ec447f84a3f4f2fc838396a1503d72d51a Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 17:18:47 +0000 Subject: [PATCH 183/204] protobuf link Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index c32e792f47..c1e43b09bc 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: ./prepare-for-fedora-rawhide.sh; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From a7799965d2b590270cc8802e462ea1a44b7500e5 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 17:46:48 +0000 Subject: [PATCH 184/204] fix ln Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index c1e43b09bc..28309ec40e 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto images/google/protobuf/descriptor.proto; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From f268371ebeb61547b33be7235bec613a996bc8b9 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Wed, 14 Apr 2021 20:20:21 +0000 Subject: [PATCH 185/204] setenforce 0 Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 28309ec40e..024dcad1d2 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: setenforce 0; ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From 318521e871f8bdb0cd9acab351899f6e5befd536 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 06:32:46 +0000 Subject: [PATCH 186/204] prepare Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 024dcad1d2..65dcee89f3 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,12 @@ require: - git - make - python3 -test: setenforce 0; ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +prepare: + how: shell + script: + - setenforce 0 + - getenforce + - ./prepare-for-fedora-rawhide.sh + - ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto +test: getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From 1359f854f9a21a8932d4e9b7f063a2271b3f66f4 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 07:06:29 +0000 Subject: [PATCH 187/204] change prepare Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 65dcee89f3..87d919eff7 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -6,10 +6,6 @@ require: - python3 prepare: how: shell - script: - - setenforce 0 - - getenforce - - ./prepare-for-fedora-rawhide.sh - - ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto -test: getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh + script: ./prepare-for-fedora-rawhide.sh +test: ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From 9e17c91077c541b11ae888c0ae6b760e7a6e3c5b Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 11:00:06 +0000 Subject: [PATCH 188/204] remove aarch64 from tests Signed-off-by: Adrian Reber --- .packit.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.packit.yaml b/.packit.yaml index 692c85e5a8..20b639800b 100644 --- a/.packit.yaml +++ b/.packit.yaml @@ -30,4 +30,3 @@ jobs: metadata: targets: - fedora-all-x86_64 - - fedora-all-aarch64 From 5244068b028c2fe4e605fa0d9deead855a080485 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 11:29:35 +0000 Subject: [PATCH 189/204] remove prepare section Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 87d919eff7..0fde9783de 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,8 +4,5 @@ require: - git - make - python3 -prepare: - how: shell - script: ./prepare-for-fedora-rawhide.sh -test: ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh duration: 60m From 8984683fcd06bac985b09a2ac4a5d61d176478e6 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 12:14:57 +0000 Subject: [PATCH 190/204] more setenforce 0 Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- scripts/ci/run-ci-tests.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 0fde9783de..4ad5cd93a6 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: ./prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh +test: sh -xc './prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' duration: 60m diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index f1ed6bcfce..c2a0983e31 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -209,6 +209,8 @@ if [ "${STREAM_TEST}" = "1" ]; then exit 0 fi +getenforce + # shellcheck disable=SC2086 ./test/zdtm.py run -a -p 2 --keep-going $ZDTM_OPTS From 350826814a48ddb161c7bd90b2a45d9efd749b2d Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 12:43:04 +0000 Subject: [PATCH 191/204] install libselinux-devel Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 4ad5cd93a6..f92aef1154 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: sh -xc './prepare-for-fedora-rawhide.sh; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' +test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' duration: 60m From d9b744fc8f0d1d178785db8e3e897d88d76293e9 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 12:53:30 +0000 Subject: [PATCH 192/204] fix missing ; Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index f92aef1154..43215f11ca 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' +test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' duration: 60m From 9f7ec7ab61b0097b89a49ef77263a2449390916b Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 13:45:12 +0000 Subject: [PATCH 193/204] disable sssd Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- scripts/ci/run-ci-tests.sh | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 43215f11ca..acc8ba280e 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' +test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel; systemctl stop sssd; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' duration: 60m diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index c2a0983e31..f1ed6bcfce 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -209,8 +209,6 @@ if [ "${STREAM_TEST}" = "1" ]; then exit 0 fi -getenforce - # shellcheck disable=SC2086 ./test/zdtm.py run -a -p 2 --keep-going $ZDTM_OPTS From 8430725b431c905878ea2f84d3c06d1e67354b94 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 14:19:41 +0000 Subject: [PATCH 194/204] enable selinux again and keep-going Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- scripts/ci/run-ci-tests.sh | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index acc8ba280e..07290222ef 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -4,5 +4,5 @@ require: - git - make - python3 -test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel; systemctl stop sssd; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; setenforce 0; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' +test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel; systemctl stop sssd; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' duration: 60m diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index f1ed6bcfce..3b844715ee 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -218,11 +218,11 @@ LAZY_TESTS='.*(maps0|uffd-events|lazy-thp|futex|fork).*' LAZY_OPTS="-p 2 -T $LAZY_TESTS $LAZY_EXCLUDE $ZDTM_OPTS" # shellcheck disable=SC2086 -./test/zdtm.py run $LAZY_OPTS --lazy-pages +./test/zdtm.py run $LAZY_OPTS --lazy-pages --keep-going # shellcheck disable=SC2086 -./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages +./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages --keep-going # shellcheck disable=SC2086 -./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages --tls +./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages --tls --keep-going bash -x ./test/jenkins/criu-fault.sh if [ "$UNAME_M" == "x86_64" ]; then From a87162e13e76db2fb2d4073f1c0f2afe5073d02b Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 14:41:59 +0000 Subject: [PATCH 195/204] echo 1 > /proc/sys/vm/unprivileged_userfaultfd Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 3b844715ee..3140f8817f 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -217,6 +217,8 @@ LAZY_EXCLUDE="-x maps04 -x cmdlinenv00 -x maps007" LAZY_TESTS='.*(maps0|uffd-events|lazy-thp|futex|fork).*' LAZY_OPTS="-p 2 -T $LAZY_TESTS $LAZY_EXCLUDE $ZDTM_OPTS" +echo 1 > /proc/sys/vm/unprivileged_userfaultfd + # shellcheck disable=SC2086 ./test/zdtm.py run $LAZY_OPTS --lazy-pages --keep-going # shellcheck disable=SC2086 From 19cd0595ec6c61f67d0afd26e8615643dd7c0479 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Thu, 15 Apr 2021 15:12:38 +0000 Subject: [PATCH 196/204] test: remove ../criu from all directory paths Signed-off-by: Adrian Reber --- test/others/libcriu/Makefile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/others/libcriu/Makefile b/test/others/libcriu/Makefile index 226396e6a0..c63c224bd6 100644 --- a/test/others/libcriu/Makefile +++ b/test/others/libcriu/Makefile @@ -1,6 +1,6 @@ -include ../../../../criu/Makefile.versions +include ../../../Makefile.versions -TESTS += test_sub +TESTS += test_sub TESTS += test_self TESTS += test_notify TESTS += test_iters @@ -15,13 +15,13 @@ run: all define genb $(1): $(1).o lib.o - gcc $$^ -L ../../../../criu/lib/c/ -L ../../../../criu/images/ -lcriu -o $$@ + gcc $$^ -L ../../../lib/c/ -L ../../../images/ -lcriu -o $$@ endef $(foreach t, $(TESTS), $(eval $(call genb, $(t)))) %.o: %.c - gcc -c $^ -iquote ../../../../criu/criu/include -I../../../../criu/lib/c/ -I../../../../criu/images/ -o $@ -Werror + gcc -c $^ -iquote ../../../criu/include -I../../../lib/c/ -I../../../images/ -o $@ -Werror clean: libcriu_clean rm -rf $(TESTS) $(TESTS:%=%.o) lib.o @@ -32,5 +32,5 @@ libcriu_clean: .PHONY: libcriu_clean libcriu: - ln -s ../../../../criu/lib/c/libcriu.so libcriu.so.${CRIU_SO_VERSION_MAJOR} + ln -s ../../../lib/c/libcriu.so libcriu.so.${CRIU_SO_VERSION_MAJOR} .PHONY: libcriu From 597adf97e7f30a997528cd7a050390c165cf1429 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 07:17:04 +0000 Subject: [PATCH 197/204] one more change Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 07290222ef..9c3cc24e70 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -1,8 +1,13 @@ summary: Run CI test suite -require: - - git - - make - - python3 -test: sh -xc './prepare-for-fedora-rawhide.sh; dnf install -y libselinux-devel; systemctl stop sssd; ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; getenforce; getenforce; dmesg; getenforce; CD_TO_TOP=1 SKIP_CI_PREP=1 CC=gcc ./run-ci-tests.sh' +environment: + CD_TO_TOP: 1 + SKIP_CI_PREP: 1 + CC: gcc +test: + - ./prepare-for-fedora-rawhide.sh + - dnf install -y libselinux-devel + - systemctl stop sssd + - ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto + - ./run-ci-tests.sh' duration: 60m From c3254304d6d46e3937d4ce4ca38d9d4c34e73ec6 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 07:41:39 +0000 Subject: [PATCH 198/204] try this Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 9c3cc24e70..5da0b38141 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -5,9 +5,9 @@ environment: SKIP_CI_PREP: 1 CC: gcc test: - - ./prepare-for-fedora-rawhide.sh - - dnf install -y libselinux-devel - - systemctl stop sssd - - ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto - - ./run-ci-tests.sh' + ./prepare-for-fedora-rawhide.sh + dnf install -y libselinux-devel + systemctl stop sssd + ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto + ./run-ci-tests.sh' duration: 60m From 19235aa9f93766fab117cbe4c7724240e401dc2f Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 07:41:45 +0000 Subject: [PATCH 199/204] allow userfaultfd in userns Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 3140f8817f..10a6173fd9 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -217,7 +217,11 @@ LAZY_EXCLUDE="-x maps04 -x cmdlinenv00 -x maps007" LAZY_TESTS='.*(maps0|uffd-events|lazy-thp|futex|fork).*' LAZY_OPTS="-p 2 -T $LAZY_TESTS $LAZY_EXCLUDE $ZDTM_OPTS" -echo 1 > /proc/sys/vm/unprivileged_userfaultfd +if [ -e /proc/sys/vm/unprivileged_userfaultfd ]; then + # Starting with 5.2 to use usefaultfd in a user space + # this needs to be set. + echo 1 > /proc/sys/vm/unprivileged_userfaultfd +fi # shellcheck disable=SC2086 ./test/zdtm.py run $LAZY_OPTS --lazy-pages --keep-going From 18885730a63108ef5c989e288d21b9589a54faf1 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 07:57:40 +0000 Subject: [PATCH 200/204] remove ' Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 5da0b38141..7a88a5c2e5 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -9,5 +9,5 @@ test: dnf install -y libselinux-devel systemctl stop sssd ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto - ./run-ci-tests.sh' + ./run-ci-tests.sh duration: 60m From 624844e78c588304daecbc56feeb788252f03ac3 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 08:09:45 +0000 Subject: [PATCH 201/204] add some ; Signed-off-by: Adrian Reber --- scripts/ci/ci.fmf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/ci/ci.fmf b/scripts/ci/ci.fmf index 7a88a5c2e5..d252389b95 100644 --- a/scripts/ci/ci.fmf +++ b/scripts/ci/ci.fmf @@ -5,9 +5,9 @@ environment: SKIP_CI_PREP: 1 CC: gcc test: - ./prepare-for-fedora-rawhide.sh - dnf install -y libselinux-devel - systemctl stop sssd - ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto + ./prepare-for-fedora-rawhide.sh; + dnf install -y libselinux-devel; + systemctl stop sssd; + ln -sf /usr/include/google/protobuf/descriptor.proto ../../images/google/protobuf/descriptor.proto; ./run-ci-tests.sh duration: 60m From b2a2a01a1b5f1f973356baaee6b4a15b26ff0080 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 08:39:39 +0000 Subject: [PATCH 202/204] Skip tun_ns on F33 Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 10a6173fd9..13c07b1f7f 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -90,6 +90,7 @@ print_header() { } print_env() { + set +x # As this script can run on multiple different CI systems # the following lines should give some context to the # evnvironment of this CI run. @@ -105,6 +106,17 @@ print_env() { [ -e /etc/lsb-release ] && cat /etc/lsb-release [ -e /etc/redhat-release ] && cat /etc/redhat-release [ -e /etc/alpine-release ] && cat /etc/alpine-release + if [ -e /etc/os-release ]; then + # shellcheck disable=SC1091 + . /etc/os-release + if [ "${NAME}" = "Fedora" ] && [ "${VERSION_ID}" = "33" ]; then + # The tun_ns test fails only on Fedora 33 with + # Error (criu/net.c:1818): IP tool failed on route save' + # Skip it + ZDTM_OPTS="$ZDTM_OPTS -x zdtm/static/tun_ns" + fi + fi + print_header "ulimit -a" ulimit -a print_header "Available memory" @@ -116,6 +128,7 @@ print_env() { fi print_header "Available CPUs" lscpu || : + set -x } print_env From 1183274084cc7e6a4a72bd447522622f440d53e8 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 12:09:30 +0000 Subject: [PATCH 203/204] Install libbsd-devel on Fedora Signed-off-by: Adrian Reber --- scripts/ci/prepare-for-fedora-rawhide.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/ci/prepare-for-fedora-rawhide.sh b/scripts/ci/prepare-for-fedora-rawhide.sh index e5900e5637..c28a684dcf 100755 --- a/scripts/ci/prepare-for-fedora-rawhide.sh +++ b/scripts/ci/prepare-for-fedora-rawhide.sh @@ -14,6 +14,7 @@ dnf install -y \ nftables-devel \ libaio-devel \ libasan \ + libbsd-devel \ libcap-devel \ libnet-devel \ libnl3-devel \ From fe31d8396aeebd8c6f5fece8467c9f426dcd4ec0 Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Fri, 16 Apr 2021 12:35:53 +0000 Subject: [PATCH 204/204] ci: skip error injection on 5.12 Signed-off-by: Adrian Reber --- scripts/ci/run-ci-tests.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index 13c07b1f7f..53ee10bbd5 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -115,6 +115,14 @@ print_env() { # Skip it ZDTM_OPTS="$ZDTM_OPTS -x zdtm/static/tun_ns" fi + if [ "${NAME}" = "Fedora" ] && [ "${VERSION_ID}" = "35" ]; then + # Error injection fails on Fedora 35 + KERN_MAJ=$(uname -r | cut -d. -f1) + KERN_MIN=$(uname -r | cut -d. -f2) + if [ "$KERN_MAJ" = "5" ] && [ "$KERN_MIN" -gt "11" ]; then + SKIP_CRIU_FAULT=1 + fi + fi fi print_header "ulimit -a" @@ -243,7 +251,10 @@ fi # shellcheck disable=SC2086 ./test/zdtm.py run $LAZY_OPTS --remote-lazy-pages --tls --keep-going -bash -x ./test/jenkins/criu-fault.sh +if [ -n "$SKIP_CRIU_FAULT" ]; then + bash -x ./test/jenkins/criu-fault.sh +fi + if [ "$UNAME_M" == "x86_64" ]; then # This fails on aarch64 (aws-graviton2) with: # 33: ERR: thread-bomb.c:49: pthread_attr_setstacksize(): 22