The dmesg output in cleanup_cgroup() makes it hard to find the
actual error in CI logs because one needs to scroll past it.
Move dmesg to dedicated CI steps that always run instead.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a "Print dmesg" step with if: always() to every GitHub
Actions job that runs CRIU tests. For VM-based tests (CentOS
Stream, VM Fedora) dmesg runs inside the VM via lima. Jobs
that only compile or run non-CRIU tests are left unchanged.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a "Print dmesg" step with when: always to the CircleCI
test-local job so kernel logs are captured even on failure.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
- Add -I../../include to CFLAGS so common/config.h is found.
- Guard the TCP queue enum in tcp-conn.c with
#ifndef CONFIG_HAS_TCP_REPAIR, matching soccr.h, to avoid
redeclaration errors on systems where <netinet/tcp.h> already
provides these symbols.
- Use libsoccr_release(so) instead of libsoccr_resume(so) for the
original socket handle whose fd was already closed, fixing a
Bad file descriptor error from setsockopt.
- Port run.py and tcp-test.py to Python 3: use bytes literals for
pipe I/O, read from sys.stdin.buffer, and decode pipe output
before parsing.
- Replace eval() with ast.literal_eval() to avoid code injection
warnings.
- Clean all test binaries in the clean target, and hook it into
the top-level make clean/mrproper via clean-top.
- Add soccr/test Python files to the top-level ruff target.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Pass name and uns as parameters to ns_flavor.__init__() instead
of overwriting them after the super constructor sets them. This
avoids the attribute-overwrite pattern flagged by CodeQL while
keeping the same behavior.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add explicit 'return None' to all code paths in __criu_act() so
that explicit returns (returning ret on the nowait path) are not
mixed with implicit fall-through returns.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The loop iteration variable 'i' in cr() is never used inside
the loop body. Rename it to '_' to indicate it is intentionally
unused and silence the CodeQL warning.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
exit() is provided by the site module for interactive use.
Use sys.exit() which is the proper way to exit from scripts.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The sys.exit(1) after a while True loop can never be reached.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The pass statements are redundant since the except blocks
already contain a print() call.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
BaseException
Replace bare except clauses with except Exception to avoid
catching BaseException subclasses like SystemExit and
KeyboardInterrupt.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
When cross-compile dependency packages cannot be installed, emit
a ::error:: annotation so that the failure reason is visible in
the GitHub Actions summary. Use \r to ensure the annotation is
recognized even inside Docker BuildKit output which prefixes
each line with step and timing information.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
duplication
Move the riscv64-specific APT repository setup (GPG keys, custom
source lists) from the template into the header file. This allows
the riscv64 template to be a symlink to the shared
Dockerfile.stable-cross.tmpl, like all other cross-compilation
targets. Skip amdgpu_plugin for riscv64 as it is not supported.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
free(NULL) is a no-op per the C standard (C99 7.20.3.2), so
guarding free() calls with NULL checks is unnecessary.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The cross compile test for riscv was always failing with repository
inconsistencies around ncurses packages. The package is not actually
needed for CRIU, so just drop it.
Signed-off-by: Adrian Reber <areber@redhat.com>
Test that SCM_CREDENTIALS ancillary messages queued in a unix
socket are correctly saved and restored by CRIU.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit a9b546c74f6c1e817b0790bd9621cc137bb719f3)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Long story short: we face standard "which was first chicken or egg?"
problem here.
1) In add_fake_unix_queuers() for each unpared established unix socket
we want to add a "fake" queuer. And we want to decide at this point
which task should create this queuer and we just try to copy the task
from original socket. But original socket can have no task yet too,
because it can have no open fds, instead it is residing inside other
unix socket.
2) In prepare_scms we look through the packets from all unix sockets and
detect file descriptors in them.
3) We need to add those packets in special queuer's list so that queuer
can understand when all files we need to put in it are already created.
So it means that we need to have "fake" queuers present at this point.
4) At the same time it is also a point to understand which task should
create those descriptors from unix sockets and we just try to copy the
task from the queuer who would put them to unix socket.
You can imagine that queuers should be created (1) before we try to copy
task from them (3) and their peer socket may only give the task to
queuers (1) after it copyes the task from it's ancestor unix socket (4).
So let's fix it with:
- Split "fake" queuer owner task detection into separate step after
handling scm
- When handling scm, if queuer has no owner task, take it from original
socket
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 82641caf2580bd941cd78df32193556ed1ae31c2)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Here is how we dump nested unix sockets inside unix sockets:
+-> dump_one_unix_fd <-+
+-> dump_sk_queue |
+-> dump_sk_queue_packet |
+-> dump_packet_cmsg |
+-> dump_one_file |
+-> do_dump_gen_file +
+-> queue_packet_entry
+-> list_add_tail(packets_list)
So in the images more deeper unix socket goes strictly before the more
shallow one.
Before this patch on restore we also had the same reverse order due to
list_add_tail used when adding to packets_list. Because of it we first
handle deeper sockets in prepare_scms and later shallow ones.
This is conterintuitive because in case of nested unix sockets without
any actual open fds on them we need to find out which task should create
them (file_master()->task) and in unix_note_scm_rights we determine this
owner from queuer which can also have it yet unset because it would be
handled later in prepare_scms.
Let's reverse the walk order on restore in prepare_scms.
Note: we can't just reverse the order in list as we rely in
restore_sk_queue that packets of one socket are in original order.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit db11de636842c29ca21e9176cd43b785c7379c56)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
We already do so in other branch of if in dup_fdinfo, let's then do it
symmetrically. We later put pointer to this FdinfoEntry in collect_fd_to
int alloc_fle to fdinfo_list_entry->fe so it can be later used from
other places and if one thread modifies it we would not see modification
in other threads.
Do we really need to see these modifications? - It's Mistery, but better
be on the safe side.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 376773c840e1b527f894e83048f0be61869c409a)
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
This would help to understand restore logs of unix sockets.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit ae1bc673960ce7679527a7fb13cb5dcf8aaf5890)
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Printing info message when we go to nested fds will make easier to
understand logs of unix sockets dumping.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit ae7cee5ef93efba90466bbf67d0e0367a05cc830)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
This allows us to catch long standing bug in vzcriu when scm-s were not
dumped properly - scm-s from second packet contained both scm-s from
first and second packet. This happenes in case there several SCM_RIGHTS
packets and at least one SCM_CREDENTIALS packets were sent to unix
socket at the same time.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 65ea504a97506355c0a5a4d9612a4827a58d6631)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
When we have several SCM_RIGHTS packets and at least one SCM_CREDENTIALS
sent simultaneousely into same unix socket we see that SCM_RIGHTS are
dumped wrong. It happens because before this patch SkPacketEntry had
been reused when dumping consequent packets, thus when dumping
SCM_RIGHTS for non-first packet it's pe.scm also contained SCM_RIGHTS
for previous packet.
To fix this let's not reuse SkPacketEntry. Also while on it let's split
dump_sk_queue_packet() - separate function for dumping one packet, to
add more readability to the code. Also drop meaningless "ret = -E2BIG"
and staff. Note that after this change pe.ucred is also not reused as it
probably should've always been.
Fixes: e4956b0b1 ("sk-queue: Add support of ucreds in unix sockets")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 6832ccd499c1bef9bc220cdf42202c468fe5a37c)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Reproducer for the next problem:
When unix socket contains SCM with SCM_CREDENTIALS
cmsg_type we have to postpone saving this packet to
CR_FD_SK_QUEUES image because we need to have information
about process which creds was transfered in this message.
But if this SkPacketEntry already contains data from
SCM_RIGHTS messages (file descriptors was transfered
through unix socket) we will lose this data because of
incorrect queue_packet_entry function implementation.
This problem tends to inconsistent CRIU dump and on
restore we will get:
Error (criu/files.c:230): Empty list on file desc id 13(5)
Error (criu/files.c:232): BUG at criu/files.c:232
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
(cherry picked from commit 6aa13217721db06b7cbd873e615580f0a455d5a7)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
If SkPacketEntry contains both SCM_CREDENTIALS and SCM_RIGHTS message
then only SCM_RIGHTS will be put into socket queue.
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
(cherry picked from commit 1aa1b1cb430e39271e7fbd44bd8609198a7f3a20)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
When unix socket contains SCM with SCM_CREDENTIALS
cmsg_type we have to postpone saving this packet to
CR_FD_SK_QUEUES image because we need to have information
about process which creds was transfered in this message.
But if this SkPacketEntry already contains data from
SCM_RIGHTS messages (file descriptors was transfered
through unix socket) we will lose this data because of
incorrect queue_packet_entry function implementation.
This problem tends to inconsistent CRIU dump and on
restore we will get:
Error (criu/files.c:230): Empty list on file desc id 13(5)
Error (criu/files.c:232): BUG at criu/files.c:232
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
(cherry picked from commit e6a9ce32ad14d18ff3160e5339e4582885d740fe)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
The queue may have a dead process' data in such case we rather
should ignore the packet.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit f854da2284c2c0163055322804aa616b17a34c28)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
For debug sake.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 318009a0ddf7150e7967f2dc52752cbb469cacd2)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
A process may send creds message and get exited
so the message will be detected on checkpoint
but we won't be able to queue it back because
process is already dead and such sending is
forbidden by kernel. So just ignore such
packets.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit e0e73bcbb8e07e60dbfd4e23cebe2f477a930704)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Checkpoint and restore ucreds on unix sockets are not
that trivial: the @pid returned by the kernel upon
message fetching is mapped to current user namespace
so it is not the same as it would be received inside
container. So we need to map real pid returned into
virtual seen from inside, but we know virtual pids
only when complete process tree is built.
Thus what we do -- queue such packets into own
queue and when process tree is build walk over
and transform former pids into virtual ones.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 8f3061c360381894a97edca2ada85466f95e1d88)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
A socket may support receiving timestamps from the
kernel (see net/socket.c:__sock_recv_timestamp
in the kernel), so simply pass up this data to
userspace.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 1ecd757bf23831d1574e1dca0566dbe26e0fcb49)
Ahmed Elaidy:
- ported as a standalone commit (was previously squashed into the
unix-sockets ucred support); only the SOL_SOCKET timestamp handling
is kept, the netlink pktinfo part of the original is not ported here.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
When error happened in dump_sk_creds or dumping
in dump_sk_queue passed fine we can leak xmalloc'ed
SkUcredEntry. Fix it.
Note it's not critical anyhow since CRIU will end up
execution in both cases and OS release memory
automatically but still.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 969a2aba0331ff940501205077766859453b9a35)
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
ucred.pid is zero for kernel messages and in this case it is
impossible to restore it.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 70948c510699aa8a2d28fc1669ad25dd81a6b102)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
We need to know a type of unsupported control messages.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 4ab24ee8840b4d879147442f4c65bb7eac77a8bb)
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
ucred in a netlink message contains the same pid and
it doesn't metter from which pidns it is read.
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
(cherry picked from commit 66f8f7b2ae51a2cef4044df478389137735e1d6e)
Ahmed Elaidy:
- dropped the ENOBUFS bits (SK_QUEUE_TRACK_ENOBUFS and the int *val
out-parameter): they belong to "netlink: save and generate ENOBUFS
at restore", which needs a non-upstream kernel extension and is
intentionally not ported.
- SK_QUEUE_DUMP_ADDR / the int flags signature come from the preceding
"sk-queue: use flags in dump_sk_queue" cherry-pick rather than being
glued in here.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
(cherry picked from commit 8b83405614703211fee27f90f08450cba080a44c)
Ahmed Elaidy:
- adapted onto the upstream 2-arg dump_sk_queue(): upstream has no
netlink queue dump, so there was no bool dump_addr argument to
convert; introduce int flags on the 2-arg base and update the only
caller (unix sockets). No sk-netlink.c change for the same reason.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
The benchmark and its five data generators otherwise remain standalone
tooling, so normal CI would not notice broken integrity checks,
statistics accounting, or compression configuration.
Add a bounded smoke run for zero, mixed, pseudorandom, text, and
ELF-derived mappings. Compare uncompressed, per-page LZ4, and 64 KiB
region images with one warmup and one measured iteration, print the
results, and fail on checksum, accounting, or configuration errors.
Run the helper tests first, then build the pycriu bindings needed by the
live benchmark. Leave the host page cache untouched and enforce a
five-minute timeout. Gate the run on compression support.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compression can fall back to raw storage for every block in an entry.
The writer then omits compression metadata so restore can use ordinary
I/O, but that fast path also depends on a page-aligned payload.
Add per-page and region tests with an incompressible mapping. Inspect
the pagemap for an aligned 56-page entry without compression metadata,
while requiring another genuine LZ4 block to prove compression was
active. Restore through direct image I/O, require native AIO when
O_DIRECT is available, and verify the workload contents.
Run the test in CI when page compression is available.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Successive layers in an incremental dump can use different compression
modes. Restore must interpret each layer through its own inventory and
pagemap metadata instead of applying the final image mode to the parent
chain.
Add chains with two pre-dumps and a final dump for plain-to-page,
page-to-plain, plain-to-region, and region-to-plain transitions. Toggle
a page between layers so every image carries real payload, check the
exact inventory version and compression settings, and restore the ZDTM
workload to verify its memory contents.
Run the test in CI when both page compression and memory dirty tracking
are available.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Benchmark output can look credible even when command construction,
configuration recovery, archive inspection, accounting, or cleanup has
drifted. Full Podman and model-serving trials are too expensive for
focused checks of those helpers.
Add fast tests that load both serving frontends against their shared
implementation while keeping their mutable state separate. Cover CRIU
option isolation, explicit automatic decompression, port-derived URLs,
inventory validation, runc.conf locking and crash recovery, metadata
preservation, secret redaction, container failure detection, response
integrity, signal handling, and cleanup.
Also verify deterministic workload generation, report normalization,
cache-control failures, and the pagemap evidence required by the
region-cache benchmark. Add the compression benchmark tree to ruff and
provide a dedicated unit target.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Serving engines have different memory layouts and restore behavior, so
SGLang results do not establish the cost or correctness of compression
for vLLM.
Add a vLLM frontend to the shared Podman benchmark. Support CPU and GPU
images and the supported server entrypoint forms, compare uncompressed,
per-page LZ4, and region LZ4 images, and verify deterministic inference
after restore. Report archive, checkpoint, restore, and post-restore
request costs, and add a bounded CPU test runner.
Reuse the shared runc.conf transaction, CRIU configuration isolation,
inventory validation, secret redaction, failure diagnostics, and
cleanup semantics so both serving benchmarks follow the same
methodology.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Process-only measurements do not show how compressed pages affect a
containerized inference server, where Podman configuration, model
startup, and service readiness are part of the restore path. SGLang
also needs content validation so a quick restore cannot hide damaged
state.
Add a CPU and GPU SGLang benchmark that checkpoints through Podman.
Compare uncompressed, per-page LZ4, and region LZ4 images. Send the same
deterministic chat request before and after restore, compare response
hashes, measure archive and operation costs, and verify the compression
mode and region size recorded in the exported inventory. Derive the
local serving URL from the selected port unless one is supplied.
Podman passes CRIU options through the host-wide runc.conf. Serialize
updates with a canonical lock and crash-recovery journal, preserve file
metadata and xattrs, refuse to overwrite external changes, and restore
the original configuration on success and during error or signal
cleanup. Isolate CRIU from ambient defaults, keep access tokens out of
arguments and diagnostics, detect stopped containers during health
checks, and preserve failed artifacts. Add a bounded CPU test runner.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Incremental restore can request alternating pages from one compressed
parent region. Without reuse, each partial request decompresses the same
block again, but a timing result is meaningful only if the images really
create that access pattern.
Add an A/B benchmark that takes a compressed pre-dump, dirties
alternating pages, and compares restore with two CRIU binaries. Publish
the workload mapping address and inspect both pagemaps before restore.
Require the requested region size and a genuine LZ4 parent block.
Require alternating present and parent pages plus at least two parent
slices from the same block.
Record that evidence with each trial, verify the restored mapping with
SHA-256, alternate binary order, and separate warmups from measured
iterations. Emit both machine-readable data and a Markdown summary.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compression effectiveness depends on page contents and block size,
while dump and restore costs can move independently of image size. The
series needs a repeatable baseline that measures those trade-offs and
rejects a fast result if restored memory is wrong.
Add a root-only benchmark for zero, mixed, pseudorandom, text, and
ELF-derived mappings. Compare uncompressed images with per-page LZ4 and
a sweep of region sizes, rotate configuration order after a warmup, and
report median storage, latency, and throughput from required CRIU
statistics. Verify every restored mapping with SHA-256 and preserve
artifacts when a trial fails.
Bound workload startup and cleanup, handle termination signals, and
make cache dropping an explicit, checked part of the methodology. Leave
CRIU's compressed-page worker width unchanged unless requested,
preserve an explicit automatic value of zero, and generate deterministic
random input on Python versions before Random.randbytes(). Support JSON
output for longer external runs.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIT can edit image metadata but cannot convert the matching page
payloads as one consistent image set. Changing either side alone can
leave pagemap, inventory, and payload data incompatible.
Add compress and decompress commands for checkpoint directories. Match
CRIU's block encoding, raw threshold, alignment, image version, parent
compatibility, and validation rules. Keep hugetlb and external-plugin
ranges raw because CRIU cannot premap them generically, and add the
Python LZ4 binding to supported dependencies.
Stage every output before replacing any image. Preserve ownership,
permissions, timestamps, xattrs, ACLs, and security metadata; create
exclusive hard-link backups; synchronize directory changes; and defer
terminating signals until the transaction has a definite result. Roll
back the complete image set after a failure and retain the recoverable
source if rollback or cleanup also fails.
Reject symlinks, non-regular images, unsupported versions, inconsistent
compression metadata, unknown modes, and truncated payloads. Recheck
source identities before replacement so a changed pathname is not
overwritten. Cover page and region images, parent chains, exceptional
mappings, metadata preservation, signals, races, and rollback failures.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
End-to-end restore tests do not isolate codec behavior or worker-pool
decisions, which makes boundary failures difficult to diagnose.
Test per-page and region round trips for zero, repeating, pseudorandom,
and single-byte inputs across several acceleration values and region
sizes. Verify zero detection, deterministic raw fallback, and page-image
offset alignment above 4 GiB.
Exercise serial and parallel LZ4 decoding and zero filling,
deterministic 0/1/N thread selection, effective-capacity gating,
work-based automatic width, growth of a persistent pool, initialization
of the shared batch budget, and return of the CPU budget. Also exercise
nonblocking acquisition and release of the second encoded input slot.
Verify that serial decoding skips caller work, while a parallel batch
runs it once after dispatch. Link the tests only when LZ4 is available.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Existing memory tests do not deliberately produce every compression
storage form or cross compression-specific batch and transport
boundaries. Regressions in zero, LZ4, raw, and mixed handling could
therefore go unnoticed.
Add neutral pages_content workloads and use them through symlinked
per-page and region-compressed variants. The same contents now run
uncompressed in ordinary sweeps, while NO_LZ4 builds skip only the
compressed variants.
Exercise compressible, incompressible, zero, mixed, file-backed, COW,
and exceptional mappings. Keep a large private zero range over nonzero
file contents so automatic restore exercises parallel zero filling when
the host has at least two available CPUs, and cannot pass by leaving an
untouched zero mapping. Size the compressible mapping at 33 MiB so
restore handles one full 32 MiB batch followed by 1 MiB of useful work.
This crosses the batch boundary with enough work to exercise read/decode
overlap. Cover pre-dump, deduplication, lazy pages, stream, direct I/O,
page server, RPC, region boundaries, incremental parent chains, and
repeated batches beyond 32 MiB. Verify restored contents in every case.
Pass both syntaxes for restore-only decompression options through the
ZDTM RPC runner. Exercise automatic concurrency in per-page and region
variants; the remaining variants retain the serial default.
Suggested-by: Andrei Vagin <avagin@google.com>
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The compression paths have no supported user or RPC controls, and
clients cannot discover whether CRIU was built with LZ4.
Expose per-page and region compression, LZ4 acceleration, and worker
concurrency for LZ4 decoding and eligible large zero fills through the
CLI, configuration files, RPC, and libcriu. Add compression to the
feature-check API and document each interface.
Define --decompress-threads=0 as automatic worker concurrency and one as
the serial default with zero-fill workers disabled. Values above one
bound aggregate worker concurrency. Automatic mode derives a useful
width from CPU affinity and the work in each batch. Reduce explicit
requests above the available CPU count with a warning.
Document the independent two-slot encoded-input budget. A local restore
overlaps its next read only when it can reserve the second slot without
waiting; otherwise it keeps synchronous I/O.
Use the compression mode as the source of truth and validate every
related value. An explicit RPC OFF clears ambient compression settings
and rejects conflicting fields. Reject combinations unsupported by page
server, stream, TLS, and image-format paths, and cover option and RPC
precedence in the tests.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compression changes the pages-image payload layout. Older CRIU versions
ignore optional pagemap metadata and would interpret packed bytes as
ordinary pages.
Introduce image version V1.2 for compressed page payloads and reject it
when CRIU lacks LZ4 support. Validate compression and version
combinations when reading inventories. Propagate V1.2 through parent
chains, including an uncompressed child of a compressed parent, while
independent uncompressed images retain the previous version.
Reject an incremental dump when its configured parent inventory is
unreadable or unsupported instead of risking a version downgrade. Keep
accepting legacy parents without dump uptime when pidfds can detect PID
reuse.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The PIE restorer cannot link against LZ4. Decode mappings containing
LZ4 payloads through CRIU's premap path, while retaining delayed PIE
restore for raw and zero ranges when a worker pool cannot help.
Classify image ranges as LZ4, raw, or zero. Decode LZ4 blocks while CRIU
still runs in its normal address space, read aligned raw ranges directly
into their final VMAs, and clear zero ranges in place. Omit compression
metadata for entries containing only raw blocks so they retain the
ordinary restore path.
Share one encoded-read context across each incremental parent chain and
reuse its worker pool for bounded batches, COW reads, streamed images,
and page-server chunks. Use the same jobs to fill zero runs of at least
1 MiB when two blocks and two CPUs are available. Zero-only ranges that
cannot benefit retain the PIE path, while zero blocks in an existing
encoded batch remain inline without effective parallel capacity. Hold
input buffers only while encoded work is active, and join every worker
before child restore or the PIE handoff.
Account calling restore threads and workers against a shared CPU budget.
A requested width of zero selects automatic concurrency, one keeps LZ4
decoding serial and disables zero-fill workers, and larger values cap
aggregate worker concurrency. Bound the active width by CPU affinity and
useful work. Release encoded-work leases before ordinary reads so idle
contexts cannot block ready workers.
Local payload-heavy restores otherwise alternate between reading an
encoded batch and decoding it. This leaves either storage or worker CPUs
idle. When a second encoded-input lease is immediately available,
dispatch the current batch to the pool and use the already-accounted
calling thread to read the next adjacent payload. Keep synchronous reads
for serial restore, streams, direct I/O, small batches, and contended
leases.
Select direct AIO from the ranges actually delayed for PIE. Batch
inherited COW comparisons and streamed payload reads, and align
page-server chunks to compression regions. Validate metadata and offset
arithmetic before allocation or I/O, roll back partially enqueued work,
and propagate worker, I/O, and deferred deduplication failures before
remapping.
On a 256 MiB pseudorandom workload with the worker limit set to eight
and three measured runs, median restore time was 114.5 ms uncompressed,
113.4 ms with LZ4 per page, and 116.5 ms with 64 KiB regions. The
previous compressed restore path took about 227 ms in either mode.
With automatic concurrency and 256 KiB regions, parallel zero filling
reduced median restore time over five runs from 103.1 ms to 31.7 ms for
zero-filled memory and from 89.3 ms to 60.0 ms for mixed memory.
On 512 MiB TEXT and ELF workloads with automatic concurrency and 256 KiB
regions, five-run median restore time fell from 117.0 ms to 110.7 ms and
from 115.4 ms to 109.5 ms, respectively.
Assisted-by: Codex:GPT-5
Assisted-by: Claude:claude-fable-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
A coalesced compressed read can allocate buffers approaching the size
of a large checkpoint and issue readahead across large, unrelated gaps.
Limit each asynchronous batch to 32 MiB of decoded pages. Split
readahead ranges when adjacent entries are more than 1 MiB apart or
their span would exceed 256 MiB. This bounds compressed input, metadata,
the decoded destination, and each individual readahead request.
Keep a split logical read transactional. If a later chunk fails, remove
newly queued requests and restore any pre-existing tail that an earlier
chunk extended.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Incremental restore can request alternating pages from one compressed
parent region. Each partial request currently reads and decompresses the
complete region again, multiplying both I/O and CPU work.
Cache the most recently decoded region in each page reader, keyed by its
virtual address and decoded size. Keep the cache across cursor advances
and resets, while duplicate readers start with independent empty caches.
A reader's pages image is immutable, so this key remains valid.
A 512 MiB mapping with 1 MiB regions was pre-dumped and then modified on
alternating pages. Across five measured restores after one warmup, the
median fell from 18.318 seconds to 0.359 seconds, a 51.1x speedup, while
every restored checksum matched.
Suggested-by: Andrei Vagin <avagin@google.com>
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Existing pagemap readers derive each pages-image offset from a fixed
PAGE_SIZE payload per present page. Packed compressed blocks make that
calculation invalid and must be reconstructed before reaching restore
destinations.
Track block and intra-region cursors while advancing, skipping, and
reading pagemap entries. Validate block counts, decoded sizes, totals,
and aligned-payload offsets before I/O. Read per-page and region images
locally, preserve ordinary parent entries, and support sequential
per-page image streams.
Carry block metadata with queued iovecs, coalesce only compatible
regions, read each packed batch once, and rebuild its destinations block
by block. Allow exactly IOV_MAX destinations and roll back iovec changes
if appending metadata fails. Decompress complete regions directly into
a contiguous destination and use scratch space for partial or split
regions. Copy the metadata into restorer memory for the later PIE decode
path.
Keep compressed images on buffered I/O, avoid hole punching packed
payloads, handle short reads, and keep compressed local reads out of PIE
until that path can decode them.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
struct page_read combines image cursors, parent traversal state, and
callbacks for several restore paths. Its terse field comments make
changes to that state difficult to review safely.
Describe each callback and cursor before compressed readers extend the
structure. Make no functional change.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Present pages are currently written as fixed PAGE_SIZE payloads. To
store packed compressed data, page transfer must choose a representation
for each block and record its size before publishing the pagemap entry.
Write zero, raw-fallback, and LZ4 blocks for individual pages or fixed
regions. Delay present pagemap entries until their block metadata is
complete, and keep region entries within one VMA so restore never splits
an LZ4 block at a VMA boundary.
Align entries whose first stored block is raw so direct restore does not
pay for mismatched file and memory page phases. Track padding in the
pages-image offset and keep variable-length compressed output on
buffered I/O.
Add a per-page compressed page-server command that sends each block size
with its payload. Validate its flags and ranges, preserve auto-dedup
ordering, and store the received representation without recompressing
it. Handle short pipe, file, and socket I/O throughout the new path.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Page-server cleanup can run after partial setup and more than once.
Partially initialized pipe arrays can still contain fd 0, while a
retained destination ID can close descriptors again after their numbers
have been reused. Setup failures and completed sessions can also leave
transfer pipes open.
Initialize pipe descriptors to -1 and clear the destination ID before
closing its image. Check pipe initialization and size queries, and close
transfer pipes when setup fails or a session completes.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The page-image writer and restore reader need a shared compression
policy before user-facing interfaces can select it.
Add internal options for the compression mode, region size, LZ4
acceleration, and worker concurrency for LZ4 decoding and large zero
fills. This gives later writer and reader changes one process-wide
source of configuration while leaving CLI and RPC exposure to a
separate change.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compressed page writers and readers need one definition of the block
format and its size limits. Duplicating those rules at each call site
would make zero, raw-fallback, and LZ4 handling easy to diverge.
Add common LZ4 helpers, zero-page detection, and shared bounds and
storage thresholds for per-page and region users. Region helpers encode
zero blocks as size zero, fall back to raw bytes when compression saves
too little, and decode all three representations. Build the
implementation only when CONFIG_LZ4 is enabled.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Present pagemap entries currently imply one PAGE_SIZE payload per page.
That is not enough to locate packed zero, raw, and LZ4 blocks or to
describe region compression.
Record the compression mode and region size in the inventory. Add
packed per-block sizes, their total, and the region width to pagemap
entries, plus PE_PAYLOAD_ALIGNED for entries whose payload starts after
padding. Keep the fields optional so ordinary and older images retain
their existing representation.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Memory page compression requires liblz4, but making it mandatory would
prevent CRIU from building on systems that do not provide it.
Detect liblz4 with pkg-config and enable CONFIG_LZ4 only when it is
available. Add NO_LZ4=1 as an explicit opt-out and register the
development package in the supported distribution dependency lists.
Install liblz4 for the per-commit build, then run a separate NO_LZ4
build and unit test to keep the optional configuration usable.
Assisted-by: Codex:GPT-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The kernel for the github actions 26.04 images fixed the kernel to no
longer have the bug that lead to the `socket-tcbuf*` failures.
Signed-off-by: Adrian Reber <areber@redhat.com>
During CI preparation, tests running inside user namespaces or
unprivileged hooks require path traversal execute permissions from
the root directory down to the current working directory.
Signed-off-by: Andrei Vagin <avagin@google.com>
When checkpointing tasks confined by stacked AppArmor profiles inside an
AppArmor namespace, CRIU compiles a permissive parasite profile using
apparmor_parser and writes it to the namespace policy replacement
interface
(/sys/kernel/security/apparmor/policy/namespaces/<ns>/.replace).
Previously, get_suspend_policy() invoked apparmor_parser with flags
(-QWL) requesting cache file generation and read the resulting cache
file. On modern AppArmor 4.x kernels, cache files include cache metadata
headers that cause the kernel policy unpacker to reject the binary blob
with EPROTONOSUPPORT (-93, "invalid profile format"). Replace the cache
mechanism by invoking apparmor_parser with the -o flag to output a clean
binary policy stream directly.
Furthermore, when writing a replacement profile blob to an AppArmor
.replace interface, successful writes return the total size of the
profile load data structure consumed or updated in the kernel (e.g.,
5233 bytes for stacked profiles), rather than the exact byte length of
the input payload (e.g., 727 bytes for a parasite profile). Checking if
(n != len) erroneously treats a successful replacement write as a
failure. Fix policy write validation to check if (n < 0).
Across Linux kernel versions, AppArmor enforces different requirements
for policy replacement blobs written to a namespace .replace interface:
- Older kernels (AppArmor 3.x / early 4.x on Ubuntu 22.04) expect blobs
compiled without namespace headers (-n <ns>); specifying -n causes
the kernel to load the replacement into a nested sub-namespace
(<ns>//<ns>), leaving the active profile unchanged and causing socket
permission failures during dump.
- Modern kernels (AppArmor 4.x on Ubuntu 26.04) reject blobs compiled
without namespace headers with EPROTONOSUPPORT (-93, "invalid profile
format").
Update get_suspend_policy() and write_aa_policy() to implement runtime
fallback: first try compiling without -n <ns> and writing directly to
the namespace interface for older kernels. If writing fails (n < 0),
retry compilation passing -n <ns> and write to the root interface to
satisfy modern kernels.
In addition, when restoring tasks confined by profiles inside an
AppArmor namespace on AppArmor 4.x kernels, the host root unconfined
profile remains stacked with the target namespace profile when viewed
from the root namespace (e.g., "unconfined//&:ns:profile"). Update
checkprofile() in the apparmor_stacking test to recognize and allow the
"unconfined//&" prefix when verifying restored profiles.
Assisted-by: Gemini
Signed-off-by: Andrei Vagin <avagin@google.com>
In file included from compel/plugins/std/infect.c:14:
compel/include/uapi/compel/asm/sigframe.h:17:8: error: redefinition of 'gcs_context'
17 | struct gcs_context {
| ^
/usr/include/aarch64-linux-gnu/asm/sigcontext.h:188:8: note: previous definition is here
188 | struct gcs_context {
| ^
Signed-off-by: Andrei Vagin <avagin@google.com>
Add an --image-io-mode passthrough to zdtm.py, set on both dump and restore
like --stream and translated into the RPC request like --pre-dump-mode. Run
maps04 with --image-io-mode=direct and maps00 with --image-io-mode=direct --rpc
in run-ci-tests.sh so the O_DIRECT dump/restore paths and the RPC handler are
exercised.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Complete --image-io-mode=direct on the dump side: for a local, non-streaming
dump, set O_DIRECT on the pages image fd in open_page_xfer() so the existing
splice() in write_pages_loc() performs direct I/O. Otherwise the dump leaves the
written pages dirty in the cache, so a same-host direct restore still has to
flush them and a large checkpoint pollutes the dump host's cache.
splice() to a file goes through iter_file_splice_write() -> ->write_iter, which
honours O_DIRECT on filesystems that support it (ext4, xfs). Where it is not
supported splice() fails with EFAULT (or EINVAL); write_pages_loc() clears
O_DIRECT, warns, and retries the remainder buffered. Only whole pages are
transferred, so the file offset stays block-aligned across the switch and the
bytes written match the buffered path, so images restore in either mode. This
keeps the transfer zero-copy: no bounce buffer and no kernel-version check.
The page server and image streaming stay buffered.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Since #3022 restore reads the pages image with O_DIRECT unconditionally. That
helps a cold or cross-host restore, but on a same-host restore it bypasses the
still-warm cache and reads from disk, which made maps04 much slower (#3053).
Add an --image-io-mode option to select the pages-image I/O method: writeback
(default) keeps the buffered behaviour, direct uses O_DIRECT. It applies to both
dump and restore and can be set on the command line or over RPC.
Gate the restore side at the probe's call sites: open_page_read_at() and the
restore vma-io builder in mem.c switch the pages fd to O_DIRECT only when direct
mode was requested, so writeback keeps reading through the host page cache. The
probe itself no longer inspects the mode; as it now runs only on an explicit
request, its buffered-fallback log becomes a warning. The dump side follows in
the next commit.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Remove the second p1.stdout.read() call which was a no-op
since p1.stdout was already fully consumed by the read() on
line 38. The result was immediately overwritten by the
p2.stdout.read() that follows.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Remove C-style pre-initialization of mnt_id to -1. The
variable is always assigned inside the loop, and the for/else
construct raises an exception if it is never set.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Remove C-style pre-initializations of variables that are always
set before use. Python does not require variables to be declared
before assignment, so sentinel values like `pid = -1`,
`status = -1`, and `stats_written = -1` are unnecessary when
the variable is unconditionally assigned in the following code.
Also drop the unused capture of __dump_process.wait() return
value in fini().
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a regex-based ignore list to grep_errors() so that known
harmless log messages do not trigger "ERROR OVER" output. This
reduces noise when running tests with ns/uns flavors where
"Address already assigned" messages are expected and benign.
This reduces CI output by at least 14400 lines (8*450*2*2):
8 lines per occurrence, ~450 tests, 2 flavors (ns and uns),
each running with and without --mntns-compat-mode.
Assisted-by: Claude Code:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Use ExitStack to ensure the conditionally-opened file for
FILE_SHARED/FILE_PRIVATE VMAs is always closed, even if an
exception occurs during seek or page iteration.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Use 'with' statement instead of manual open/read/close to
ensure the file is closed if read() raises an exception.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Use 'with' statement for opening /proc fdinfo to ensure the
file handle is closed after iteration.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Use 'with' statements for both input and output file handles
to ensure they are closed on exceptions.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Close the fd from os.open("/dev/null") after dup2, matching
the pattern used for stdout/stderr a few lines above. Also
convert __dump_meta() and dump() to use 'with' statements
for all file opens.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Use 'with' statement instead of open().read() to ensure the
file handle is properly closed.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
Convert inf(), outf(), and dinf() to context managers and update
all call sites to use 'with' statements. For inf() and outf(),
only close the handle when it is a real file, not sys.stdin or
sys.stdout.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
The service socket now defaults to 0600 (owner-only). Since the
test runs the setuid criu binary as a non-root user (uid 1000),
the socket ends up owned by root. Chown the socket to the test
user after service startup so it can connect, mirroring what an
administrator would do in production.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Generated with Claude Code (https://claude.ai/code)
Signed-off-by: Adrian Reber <areber@redhat.com>
Change the service socket permissions from 0666 (world-accessible)
to 0600 (owner-only) to prevent unauthorized local users from
connecting to the CRIU service socket.
Print a message informing the administrator that the socket is
restricted and that chmod should be used to widen access if needed.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Generated with Claude Code (https://claude.ai/code)
Signed-off-by: Adrian Reber <areber@redhat.com>
Third-party GitHub Actions referenced by tags can change without a CRIU
patch if the upstream action repository moves or compromises a tag. That
is especially sensitive for actions that receive CI credentials such as
CODECOV_TOKEN or GITHUB_TOKEN.
Pin the remaining non-GitHub actions used by regular workflows to the
full commit IDs currently behind their version tags. Keep the version
tag in a comment next to each SHA so reviewers can see the intended
release and future updates remain explicit.
Leave GitHub-owned actions on version tags to match the existing
linux-next workflow policy, which already pins non-GitHub actions while
using tags for actions/* refs. This keeps the hardening focused on
third-party supply chain risk without forcing the repository-wide SHA
policy that would also require pinning GitHub-authored actions.
Fixes: #3068
Assisted-by: Codex:gpt-5
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Replace 'from .images import *' with an explicit import list to
prevent namespace pollution, as the images module does not define
'__all__'.
Assisted-by: Claude Code (claude-opus-4-6@default)
Signed-off-by: Adrian Reber <areber@redhat.com>
ctrl_dir_and_opt() builds comma-separated controller directory and
mount option strings by repeatedly appending via snprintf() into
stack-allocated buffers. The offsets (doff, ooff) are advanced by
the snprintf() return value, but snprintf() returns the number of
bytes that *would* have been written on truncation, not the number
actually written. When a controller name is long enough to cause
truncation, the offset advances past the buffer end. On the next
iteration, the remaining-length calculation (e.g. ds - doff) goes
negative and is implicitly cast to a large size_t, disabling the
truncation guard entirely. Subsequent snprintf() calls and the
trailing-comma removal then write out of bounds on the stack
(CWE-121: Stack-based Buffer Overflow).
A crafted cgroup.img with oversized cnames entries triggers this
during restore in any code path that calls ctrl_dir_and_opt():
prepare_cgns(), move_in_cgroup(), prepare_cgroup_properties(),
prepare_cgroup_sfd(), and cgroupd().
Fix this by checking every snprintf() call for truncation before
advancing the offset. Each append now verifies that remaining
space is positive and that snprintf() did not return a value
greater than or equal to the remaining space. On any overflow
the function returns -1 and all five callers now propagate this
error. Also change the type of `off` in prepare_cgroup_properties()
from unsigned int to int so the -1 return is not silently converted
to a large positive value.
This vulnerability was identified and analyzed by an AI security
analysis tool.
Assisted-by: claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
A not-accountable VMA cannot hold restored pages. If such a VMA is
matched into the COW chain, a child can inherit a parent's PROT_NONE
reservation as the target for its restored memory.
Reject not-accountable VMAs when preparing COW relationships. This makes
the child restore its pages through a separate writable premap, while the
parent's PROT_NONE reservation can still be mapped without write access.
Signed-off-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The asyncd worker threads added in this series call pr_*() concurrently
on restore, but vprint_on_level() formatted every line into a shared
static buffer, so their output could interleave and garble log lines.
Build each line on the stack instead. Only the small read-only pid
prefix ("%6d: ") stays in process state -- written once per task in
log_init_by_pid() before any asyncd worker starts. Emitted bytes are
unchanged.
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
When restoring an anonymous shared memory VMA, CRIU uses a memfd if the
kernel supports it and otherwise falls back to an anonymous shared mapping
opened via map_files. Route both through the async fill daemon so the
content is filled in parallel with the rest of restore.
The map_files fallback fd of an anonymous shared mapping must not be
ftruncate()d, while a memfd must. Introduce restore_shmem_fd_content(),
which takes a truncate flag, and keep restore_memfd_shmem_content() as a
truncate=true wrapper. open_shmem() offloads the fill to the daemon and
passes truncate only for the memfd case.
As with memfd inodes, the content is filled inline when restoring from a
stream, where the daemon's out-of-band reads are not possible.
Co-developed-by: Dan Feigin <dfeigin@nvidia.com>
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
memfds are restored as regular files, so their content can be filled in
parallel at the file level. Filling memfd data is the slowest part of
restore, and since the other restore steps do not depend on it, it can be
done asynchronously by a helper daemon.
Each restoring task creates its memfd and hands the descriptor to an
asynchronous daemon (asyncd) that fills the content (mmap + pread) from a
pool of worker threads. The daemon mirrors the usernsd design: tasks ship
work over a SEQPACKET socket via SCM_RIGHTS, and the content fill runs
out-of-band while the tasks keep restoring.
The daemon's worker threads must not hold a TID that the restorer later
needs. The restorer recreates each application thread at its original TID
via clone3(set_tid); if a daemon worker still occupies that TID the clone
fails with EEXIST ("Unable to create a thread: -17"). To guarantee the
daemon is gone before any application thread is cloned, a new restore
stage CR_STATE_PRE_RESTORER is introduced between CR_STATE_FORKING and
CR_STATE_RESTORE. The root task starts the daemon and switches all tasks
to PRE_RESTORER, during which the tasks ship their fills. The root task
then drains and reaps the daemon (stop_asyncd) before switching to
CR_STATE_RESTORE, where threads are cloned. Because the daemon is reaped
first, its worker TIDs are free by the time clone3(set_tid) runs.
Keeping the daemon inside the restored task tree (rather than forking it
from the coordinator) keeps the content fill charged to the restored
container's memory cgroup instead of to criu.
The fill-thread pool is sized to min(online_cpus, 16). stop_asyncd() fails
the restore if the daemon exits abnormally, so a failed content fill is
never silently lost, and it is idempotent so the restore paths can call it
unconditionally.
criu-image-streamer serves the image in a single sequential pass, which is
incompatible with the daemon's out-of-band reads, so the daemon is not
started when restoring from a stream and the content is filled inline
instead.
Co-developed-by: Dan Feigin <dfeigin@nvidia.com>
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
Parallel memfd restore opens page images from multiple pthread workers
later in this series. Those paths can use bfd helpers, whose global
buffer pool was previously single-threaded.
Protect the shared buffer list around allocation, return, and buffer
extension paths. Add pthread linkage for the new restore-time pthread
users.
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Codex:gpt-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Add a memfd mmap test that keeps many independent memfds alive across
checkpoint and restore, with shared and private mappings for each one.
Verify restored fd flags and offsets, mapping devices, shared mapping
contents, private COW contents, and post-restore shared/private write
semantics.
Assisted-by: Codex:gpt-5
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Correct the documentation regarding `vmsplice` and `SPLICE_F_GIFT`
behavior. `SPLICE_F_GIFT` does not enforce Copy-on-Write (COW) when the
user-space process modifies the gifted memory. Instead, it is a
zero-copy mechanism where post-resume modifications can lead to
inconsistent intermediate dumps.
Explain how CRIU handles this inconsistency via its iterative design,
relying on the soft-dirty tracker to catch post-resume modifications and
re-dump them in subsequent iterations, ensuring final consistency.
Also emphasize that the `splice` scheme relies heavily on `vmsplice`
performance to minimize freeze time, making the migration almost
invisible to the process.
Signed-off-by: Andrei Vagin <avagin@google.com>
Commit 2d2168fc9 hardcodes ELFDATA2LSB in place of a previously used
endian-aware macro BORD, causing issues on big endian architectures,
e.g., on s390x:
$ ./criu/criu check -v4
(00.000000) CRIU run id = 6b0cc8b9-0cbe-44e7-aeb4-7387862d9670
(00.000016) Version: 4.2 (gitid v4.2-211-g4d76d1acd)
[...]
(00.061309) vdso: Parsing at 3ffc75ae000 3ffc75b0000
(00.061319) Error (criu/pie-util-vdso.c:126): vdso: Unsupported ELF data encoding: 2
(00.061320) Error (criu/vdso.c:633): vdso: Failed to fill self vdso symtable
(00.061321) Error (criu/kerndat.c:2043): kerndat_vdso_fill_symtable failed when initializing kerndat.
(00.061367) Adjust mmap_min_addr 0x1000 -> 0x10000
(00.061368) Found mmap_min_addr 0x10000
(00.061374) files stat: fs/nr_open 1073741816
(00.061375) Error (criu/crtools.c:280): Could not initialize kernel features detection.
Fixes: 2d2168fc9 ("vdso: relax EI_OSABI check to support linux in ELF header")
Signed-off-by: Čestmír Kalina <ckalina@redhat.com>
There is no need to use the fd libdrm duplicated from the original fd.
Just use the original one.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Simplify a bunch of error handling blocks by freeing the vm_info_entries
array as soon as we are done accessing it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Instead of initializing and de-initializing libdrm for every buffer object
we dump (each of which consists of a few system calls), we can simply
initialize it once and by doing so simplify a bunch of the error handling
blocks.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
When saving buffer object content the current code constantly allocates
and frees aligned memory where the GPU will copy each buffer one by one.
We can optimise this path by keeping the buffer around and only grow it if
is too small for the current object.
While doing this we also fix a theoretically incorrect freeing of memory
allocated via posix_memalign with xfree.
An alternative solution could be to probe for the maximum size before hand
by adding a pre-scan loop.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
amdgpu_plugin_drm_dump_file() already defines a large temporary stack
buffer for the purpose of generating the file level protobuf image name.
Instead of the buffer object dumping loop defining a separate temporary
stack buffer for the buffer content protobuf images we can simply use the
top level one.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
We can save a few lines of code and end up with a potentially more
readable function if we replace the open-coded try-retry of getting the
list of buffer objects with a loop.
While refactoring we also remove the needless copy of the entry as the
dump loop iterates the handles, and also stop returning a false success
with a made up zero buffer objects saved in cases when the kernel does not
support the DRM_IOCTL_AMDGPU_GEM_LIST_HANDLES ioctl.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
The DRM minor local variable is shadowed between two blocks inside
amdgpu_plugin_drm_dump_file(). If at the top level we access the minor via
the copy stored in the protobuf image, we can simply drop this copy and
so avoid the buffer object dump loop shadowing it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
If the protobuf image allocation fails we can simply return immediately
since there aren't any other things to clean up at this point.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Pass show_test_info directly to map() instead of wrapping it
in a redundant lambda.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
tempfile.mktemp is deprecated because it only generates a filename
without creating the file, introducing a TOCTOU race condition where
another process could create a file with the same name between the
mktemp call and the subsequent file operation.
Replace it with tempfile.mkstemp, which atomically creates the file
and returns a file descriptor, eliminating the race window.
Assisted-by: Claude Code (claude-opus-4-6)
Signed-off-by: Adrian Reber <areber@redhat.com>
When restoring inside a user namespace on a host where userfaultfd
is restricted to privileged callers, 'criu restore --lazy-pages'
fails to open a userfaultfd descriptor with EPERM. This patch improves
the error message to suggests how to fix this.
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Add a ZDTM test that verifies inotify watches on files inside an
overlayfs mount survive checkpoint/restore.
The test uses the external mount pattern (like mnt_ext_auto): in
the ZDTM_NEWNS=1 phase it creates an overlay mount before
unshare(CLONE_NEWNS), so CRIU treats it as an external mount and
does not attempt to reconstruct the overlay on restore. After
restore the test opens the watched file and reads back the inotify
event to confirm the watch is intact.
This is needed because the test/others/overlayfs test only checks
that the process survives C/R. This ZDTM test validates that the
inotify watch itself is properly dumped and restored by exercising
the overlay directory walk fallback added in fsnotify.c.
The test is restricted to the 'ns' flavor because the overlay
setup requires the ZDTM_NEWNS=1 lifecycle and root privileges
for mounting overlayfs.
Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a test that exercises checkpoint/restore of a process with an
inotify watch on a file inside an overlayfs mount.
The test compiles inotify_test.c (a simple program that sets up an
inotify watch and blocks reading events), starts it watching a file
on an overlay mount, dumps and restores via criu, then verifies the
restored process is still alive.
Run with: make -C test/others/overlayfs run-inotify
Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
When a process has inotify (or fanotify) watches on files inside an
overlayfs mount, criu dump fails because open_by_handle_at() does not
work for overlay file handles (type OVL_FILEID_V1 = 0xf8). The dump
log shows:
fsnotify: wd 0x000001 s_dev 0x00002d i_ino 0x101ad2 mask 0x00033a
fsnotify: [fhandle] bytes 0x000020 type 0x0000f8 ...
fsnotify: Handle 0x2d:0x101ad2 cannot be opened
Error (criu/fsnotify.c:284): fsnotify: Can't dump that handle
To reproduce manually:
mkdir -p /tmp/{lower,upper,work,merged}
touch /tmp/lower/testfile
mount -t overlay overlay \
-o lowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/work \
/tmp/merged
inotifywait -m /tmp/merged/testfile &
PID=$!
criu dump -t $PID -D /tmp/imgs --shell-job --ext-unix-sk
alloc_openable() iterates mounts matching s_dev and tries
open_by_handle_at() for each one. Overlay file handles use the
private OVL_FILEID_V1 type which open_by_handle_at() does not
support, so the call always fails and the dump aborts.
Add a fallback for overlay mounts: when open_by_handle_at() fails
and the mount is identified as FSTYPE__OVERLAYFS, walk the overlay
mount's directory tree with opendir/readdir/fstatat to find the
file matching the (s_dev, i_ino) pair from the handle. Store the
discovered absolute path in f_handle->path so that get_mark_path()
uses the path-based openat() strategy on restore, which works on
overlay mounts.
The fallback only triggers when open_by_handle_at() fails AND the
mount type is FSTYPE__OVERLAYFS, so there is no impact on other
filesystems.
Assisted-by: Claude Code (claude-opus-4-6):default
Signed-off-by: Adrian Reber <areber@redhat.com>
Commit 2e30db5c3d added --network-lock handling and a CLI restore
warning that checks argv[optind] after option parsing.
However, CRIU can also call parse_options() from the RPC config parsing
path with argc == 0 and argv == NULL. This path was added by 99d52ec7dd
for req->config_file handling.
If an RPC configuration file contains "network-lock iptables",
has_network_lock_opt is set and the restore warning dereferences
argv[optind], crashing criu swrk.
Guard the restore warning with argv && optind < argc before accessing
argv[optind].
Fixes: 2e30db5c3d ("criu: add --network-lock option to allow nftables alternative")
Signed-off-by: Zhang Xuedong <2190206983@qq.com>
Add a test for the SIGSEGV fixed by "mem: keep COW root VMAs writable
when premapping".
The parent reserves an address range with PROT_NONE and never touches
it, so the kernel does not account it (no "ac" flag in smaps). After
fork(), the child turns the same range into a writable mapping and fills
it with data. CRIU matches COW VMAs by start/end and flags but ignores
their protection bits, so the parent's PROT_NONE, not-accountable VMA
becomes the COW root of the child's data VMA.
On restore the child inherits the root's mapping. Without the fix that
mapping is PROT_NONE, so restoring the child's pages into it faults and
the test fails at restore; with the fix it passes.
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Commit 7daaa11aa ("mem: don't PROT_WRITE on reservation mmaps") started
to premap PROT_NONE and not-accountable VMAs with PROT_NONE, on the
assumption that such an area is only used to reserve address space and
will never get any data written into it.
That assumption does not hold for a COW root. check_cow_vmas() pairs two
VMAs that coincide by start/end and flags regardless of their protection
bits, so a parent's PROT_NONE, not-accountable reservation can become the
COW root of a child VMA that does have pages. premap_private_vma() maps
the root with PROT_NONE, the inherited child re-positions that mapping
with mremap(), and restore_priv_vma_content() then restores the child's
pages into it. Writing to (or memcmp()-ing against) a PROT_NONE mapping
faults, so the restored task dies:
(00.012587) 109: pr109-2 Read 409000 1 pages'
(00.012588) 109: \tpr109-2 Read page from self 409000/2000'
(00.012744) 109: pr109-2 Read 7f7bf9b2e000 1 pages'
(00.012745) 109: \tpr109-2 Read page from self 7f7bf9b2e000/3000'
(00.051495) 108: Error (criu/cr-restore.c:1268): 109 killed by signal 11: Segmentation fault'
This is easy to hit with an incremental dump of a process tree that keeps
re-mapping memory (e.g. zdtm/transition/maps007 with --pre and a forked
child), where a now-PROT_NONE region still has content in a child.
To fix this, restrict the PROT_NONE optimization to standalone VMAs
(vma->pvma == NULL). A COW root (vma->pvma == VMA_COW_ROOT) must stay
writable because its premapped area is shared via mremap() with
inherited children that may carry data.
Fixes: 7daaa11aa0 ("mem: don't PROT_WRITE on reservation mmaps")
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Fix four "unused local/global variable" alerts reported by CodeQL:
- zdtm.py: drop unused assignment to print_next in the tail-printing
loop at the end of grep_errors(). The return value of print_error()
is not needed here since no further iterations follow.
- crit-recode.py: remove duplicate pycriu.images.dumps(pb) call
inside the except handler. The same call just raised the exception,
so re-executing it would raise again and prevent the error message
from being printed.
- exhaustive/unix.py: drop unused msg variable. The recv() call is
used for its blocking side effect to synchronize with the parent,
the received data is not needed.
- others/mounts/mounts.py: rename unused loop variable i to _ in
the range(10) iteration.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
The tst.available() and criu.available() calls were running
unconditionally for every zdtm.py subcommand (clean, list,
group, run). The zdtm_test.available() method builds umount2,
zdtm_ct, the zdtm test library, and potentially other targets.
This caused "make -C test clean" to first build all these
binaries via "./zdtm.py clean nsroot" before deleting them.
Skip the available() calls only for the clean subcommand, as
list and group still need the test binaries to be built.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
The clean target referenced libcriu, rpc, and crit directories
directly, but these are located under others/. This caused
"make -C test clean" to fail with "No such file or directory"
when reaching the sub-make calls.
Fix the paths to others/libcriu, others/rpc, and others/crit.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
test_iters.c:29:1: error: non-void function does not return a value [-Werror,-Wreturn-type]
29 | }
| ^
1 error generated.
make: *** [Makefile:48: test_iters.o] Error 1
Signed-off-by: Adrian Reber <areber@redhat.com>
The custom core dump handler tries to call gdb which makes it much
easier to understand why something crashed especially in CI. For dnf
based distribution this currently does not work because gdb is missing.
This installs gdb on dnf based CI runs.
Signed-off-by: Adrian Reber <areber@redhat.com>
By default GitHub Actions cancels all in-progress and queued matrix
legs as soon as one leg fails (fail-fast: true). Re-running only the
failed job afterwards does not bring back the cancelled siblings, so
recovering from a single failure requires re-running the whole job.
Cancelling the siblings also hides information: whether the other
shards or environments would have passed or failed is exactly
what we want to know from a CI run, not something to discard
on the first failure. Set fail-fast: false on the matrix jobs
that were still inheriting the default, so every leg runs
to completion independently.
Assisted-by: Claude Code:claude-opus-4-8
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Move the two remaining Cirrus CI Vagrant-based tests (no-VDSO and
non-root) into the existing vm-fedora-rawhide-test GitHub Actions
matrix job using Lima VMs.
Add fedora-no-vdso-{setup,test} and fedora-non-root-{setup,test}
functions to scripts/ci/lima.sh, expand the matrix in ci.yml with
the two new variants, make the reboot step conditional on
matrix.reboot, and remove .cirrus.yml and scripts/ci/vagrant.sh
along with their Makefile targets.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
The tests are no longer vagrant based. Remove it. Instead of naming it
lima based tests, just name it VM based tests.
Signed-off-by: Adrian Reber <areber@redhat.com>
Move the CentOS Stream 9 based test from Cirrus CI to GitHub
Actions using Lima VMs. Expand coverage to a matrix of CentOS
Stream 9 and 10 on x86_64.
Extract the common Lima VM setup steps (Lima install, image
caching, KVM enablement, VM start, source copy) into a reusable
composite action at .github/actions/lima-vm-setup.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
The thread-bomb test frequently fails during setup with
pthread_create() returning EAGAIN (errno 11). The test creates
1024 threads in a tight loop from main(), and each of those
threads immediately spawns another thread that joins its
predecessor, resulting in a burst of ~2048 simultaneous thread
creations with 64KB stacks.
This burst causes transient EAGAIN errors from clone() due to
kernel resource pressure (VMA allocator contention, temporary
memory fragmentation, etc.). The failure is not related to hard
resource limits — ulimit, threads-max, max_map_count and cgroup
pids limits are all well above the required values. The failure
occurs both inside and outside containers and is worse on hosts
with fewer resources.
Measured failure rates on a 16GB / 9-CPU host:
Before fix: 65% failure rate (13/20 outside container)
After fix: ~2.5% failure rate (1/40), and that failure was
a C/R issue, not a pthread_create EAGAIN
Fix this by adding a pthread_create_retry() wrapper that retries
pthread_create() up to 50 times with a 10ms delay when it returns
EAGAIN. This gives the kernel time to reclaim resources between
attempts while keeping the total worst-case retry time under one
second per thread creation.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
CRIU dumps and restores the SO_SNDTIMEO and SO_RCVTIMEO socket
send/receive timeout options in dump_socket_opts()/restore_socket_opts()
(criu/sockets.c), but the ZDTM suite has no dedicated coverage for them:
SO_SNDTIMEO is not exercised by any test, and SO_RCVTIMEO is only used
incidentally as a receive timeout in socket_icmp, never asserted across
checkpoint/restore.
Add socket-timeo, which sets distinct send and receive timeouts on a
socket, performs checkpoint/restore, and verifies both values survive.
Whole-second timeouts are used because the kernel stores these options
with jiffy granularity: setsockopt() may round a sub-second value to the
nearest tick depending on HZ, so a literal sub-second expectation could
fail to match the stored value regardless of checkpoint/restore. The
send and receive values differ so a mix-up between the two options is
caught.
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Rocker Zhang <zhang.rocker.liyuan@gmail.com>
The amdgpu plugin's local amdgpu_drm.h defines struct
drm_color_ctm_3x4 guarded by #ifndef HAVE_DRM_COLOR_CTM_3X4,
but HAVE_DRM_COLOR_CTM_3X4 was never defined by the build
system. On systems where libdrm headers already provide this
struct (e.g. Alpine with libdrm 2.4.131), clang rejects the
redefinition as a hard error, while gcc silently accepts
identical struct redefinitions as an extension.
Add a feature test that checks whether struct drm_color_ctm_3x4
is available in the system drm_mode.h and pass
-DHAVE_DRM_COLOR_CTM_3X4 when it is, so the local fallback
definition is skipped.
Assisted-by: Claude Code (claude-opus-4-6):2025-09-03
Signed-off-by: Adrian Reber <areber@redhat.com>
The CLANG=1 parameter was only used during the Docker image build
but never propagated to the container at runtime. The hardcoded
CC=gcc in docker.env always took precedence, causing the test
container to rebuild and test with gcc instead of clang.
Override CC and HOSTCC via docker run -e flags when CLANG is set.
Signed-off-by: Adrian Reber <areber@redhat.com>
Apply the same ZDTM test sharding strategy used by the Alpine CI
job to the Arch Linux CI job (GCC only). The ZDTM tests are split
across 4 shards (indices 0-3) with a 5th shard for non-shardable
tests (lazy pages, fault injection, plugins, etc.).
This reduces the Arch Linux CI time from ~30 minutes to ~10 minutes.
Assisted-by: Claude Code (https://claude.ai/code):claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
- Explain the profile identification and namespace dumping process
- Document the use of the 'parasite profile' for non-disruptive dumping
- Detail policy loading via apparmor_parser and namespace reconstruction
- Support for modern features like Profile Stacking
- List kernel and filesystem requirements
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the hardware-assisted shadow stack mechanism
- Document the state capture via NT_ARM_GCS ptrace regset
- Detail restoration using map_shadow_stack and sigframe integration
- List kernel requirements for AArch64 hosts
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain how zombies are identified and their exit codes captured
- Describe the 'helper technique' for restoring zombies via immediate exit
- Detail parent-child coordination to prevent premature reaping
- Add references to related technical documentation
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the decouplling of socket paths and inodes
- Document the SIOCUNIXFILE ioctl for stable handle retrieval
- Describe the restoration workflow (tmpfs yard, peer coordination)
- Explain the capture and redelivery of in-flight file descriptors
- Clarify handling of external Unix sockets
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the address and ABI mismatch challenges
- Detail the Proxy (Patching) method for older kernels
- Document the modern arch_prctl method for native vDSO mapping
- Explain the role and restoration of the VVAR data region
- Mention automatic feature detection via Kerndat
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain Build-ID extraction (ELF magic, 1MB mapping)
- Document 'buildid' (default) vs 'filesize' methods
- Explain the automatic fallback mechanism
- Describe the importance for security and memory pointer integrity
- Detail usage via the --file-validation flag
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the mechanics of Lazy Migration and on-demand page loading
- Detail the Lazy Pages Daemon and the UFFD descriptor handover (SCM_RIGHTS)
- Document the use of non-cooperative UFFD features (Fork, Remap, Unmap)
- Describe the page fault handling loop and page server integration
- Clarify benefits and trade-offs of the lazy approach
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the capture of device attributes (TUN vs TAP, Flags)
- Explain index preservation using TUNSETIFINDEX
- Document multi-queue support and re-attachment via TUNSETQUEUE
- Clarify current limitations (BPF filters, in-flight packets)
- Explain persistency management during restoration
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the PTY index restoration 'brute-force' strategy
- Detail the capture of termios, winsize, and ownership
- Describe the restoration workflow for master and slave peers
- Clarify the status of buffered data and legacy BSD PTYs
- Document the re-binding of controlling terminals (TIOCSCTTY)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the mechanics of TCP Repair Mode and state manipulation
- Explain the role of libsoccr in capturing sequence numbers and options
- Document the network locking workflow using nftables/iptables
- Describe the 'Silent Close' technique to preserve peer connections
- Highlight the importance of sequence number and window restoration
Signed-off-by: Andrei Vagin <avagin@google.com>
- Formalize the CR_STATE_* state machine and synchronization mechanism
- Detail the multi-stage restoration workflow (Root Task, NS Prep, Forking, etc.)
- Explain the security rationale for Stage 6 (Credentials and Seccomp)
- Document the final transition via sigreturn and thread restoration
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the use of sock_diag for kernel state extraction
- Describe the SCM_RIGHTS mechanism for queue inspection
- Detail TCP Repair Mode for connection restoration
- List supported families including Netlink and Packet sockets
- Improve overall structure and technical depth
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the use of internal inode numbers (shmid) for anonymous sharing
- Detail the restoration of shared anonymous regions via memfd_create()
- Describe the 'master' vs 'slave' roles and futex synchronization
- Document System V IPC and file-backed shared mapping restoration
- Add references to kcmp and memory dumping optimizations
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the top-down allocation strategy using RLIMIT_NOFILE
- Explain per-process isolation (service_fd_id) for shared FD tables
- Document the relocation mechanism (F_DUPFD_CLOEXEC, dup3)
- Describe the 'sfds_protected' flag and safety invariants
- List common Service FD types (LOG, IMG, RPC, TRANSPORT, etc.)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the necessity of a dedicated context for memory swapping
- Describe the shared restorer mapping and mremap-based re-positioning
- Detail the safe hole detection strategy to avoid VMA conflicts
- Document the final transition via sigreturn
- Highlight the characteristics of the freestanding PIE blob
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the sensitivity of rseq state to process execution
- Document the use of PTRACE_GET_RSEQ_CONF and external peeking
- Detail the critical requirement to unregister the restorer's own rseq
- Explain how re-registration and rseq_cs restoration ensure automatic kernel fixups
- Update kernel requirements (v5.13 for automated detection)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain stable identification vs numeric PIDs
- Detail restoration of alive vs dead processes
- Document the 'helper process' trick for dead pidfds
- Explain the transition from anonymous inodes to pidfs (kernel v6.9+)
- Clarify current limitations (PIDFD_THREAD)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the PID reuse problem during iterative migration
- Document the use of pidfd_open() for race-free identification
- Detail the 'socket trick' for persistent FD storage via SCM_RIGHTS
- Explain the identity verification process in subsequent iterations
- List required kernel features (pidfd_open, pidfd_getfd)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the legacy ns_last_pid interface and its limitations
- Detail the modern clone3() with set_tid mechanism (kernel v5.5+)
- Describe the benefits of atomic PID assignment and nested namespace support
- Mention automatic feature detection via Kerndat
- Document implementation using architecture-specific assembly wrappers
Signed-off-by: Andrei Vagin <avagin@google.com>
- Document the use of PTRACE_PEEKSIGINFO (kernel v3.10+) for dumping
- Explain the distinction between shared and private pending signals
- Detail the batch processing of signal queues
- Explain the usage of rt_sigqueueinfo and rt_tgsigqueueinfo for restoration
- Clarify the importance of PTRACE_GETSIGMASK
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the multi-stage infection process using ptrace
- Explain memory exchange optimization via memfd
- Describe the PIE relocation and GOT patching
- Explain the daemon mode and request-response control loop
- Document the 'cure' operation for returning tasks to their original state
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the 2MB sliding window (PMC_SIZE) mechanism
- Describe greedy prefetching for adjacent small VMAs
- Document the usage of ioctl(PAGEMAP_SCAN) on modern kernels
- Clarify cache invalidation strategies during dump phases
- Mention the CRIU_PMC_OFF environment variable for debugging
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain 'splice' (default) vs 'read' (traditional) pre-dump modes
- Detail the zero-copy gifting mechanism using vmsplice() and SPLICE_F_GIFT
- Explain how COW ensures consistency while capturing memory from running tasks
- Describe parallel draining of pages to minimize freeze time
Signed-off-by: Andrei Vagin <avagin@google.com>
- Formalize the stages of the Mount V2 engine
- Explain the role of the Root Yard (root_yard_mp)
- Describe pre-fork plain mounting and source resolution
- Detail propagation restoration via MOVE_MOUNT_SET_GROUP
- Explain the final pivot_root and post-fork fixup stages
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the shift from path-based to FD-based mounting
- Detail the use of detached mounts via open_tree() and fsopen()
- Describe propagation grouping via MOVE_MOUNT_SET_GROUP (v5.15+)
- Explain the tree construction and atomic final attachment process
- Update kernel requirements and fallback behavior
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail key information captured from /proc/pid/mountinfo
- Explain the restoration challenges (dependencies, propagation)
- Document the Mount V2 engine and its benefits
- Explain external mount mapping and auto-detection
- List common issues like overmounts and unsupported filesystems
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the in_parent flag in pagemap entries
- Detail detection of unchanged pages via soft-dirty bit
- Document the --auto-dedup mode for dump and restore
- Describe online disk space reclamation using FALLOC_FL_PUNCH_HOLE
- Clarify image chaining and sparse file support
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the multi-stage dumping approach involving parasite injection
- Explain zero-copy dumping using vmsplice() and SPLICE_F_GIFT
- Describe the use of splice() for efficient image writing and page server transport
- Document VMA re-mapping and content filling during restoration
- Add references to COW preservation and lazy migration (userfaultfd)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the soft-dirty bit mechanism for tracking modified pages
- Document the usage of ioctl(PAGEMAP_SCAN) for efficient scanning (kernel v6.7+)
- Describe the iterative pre-dump workflow and image chaining
- Detail the consolidation of pages during restoration
- Mention the role of the page server in minimizing disk I/O
Signed-off-by: Andrei Vagin <avagin@google.com>
- Clarify feature detection for system calls, filesystems, and namespaces
- Update persistent caching locations (/run/criu.kdat vs XDG_RUNTIME_DIR)
- Distinguish between kerndat (host capabilities) and inventory (checkpoint metadata)
- Mention 'criu check --extra' for runtime inspection
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the kernel pointer comparison mechanism of kcmp()
- Describe the two-level red-black tree optimization (genid + kcmp sub-tree)
- List all supported KCMP_* types (FILE, VM, FILES, FS, EPOLL_TFD, etc.)
- Clarify how genid minimizes expensive system calls
Signed-off-by: Andrei Vagin <avagin@google.com>
- Describe the (inode, device) to path resolution problem
- List default heuristic scan hints (/etc, /var/log, etc.)
- Explain user-defined scan paths via --irmap-scan-path
- Detail the pre-dump optimization and irmap-cache.img
- Clarify the status of Irmap vs open_by_handle_at on modern kernels
Signed-off-by: Andrei Vagin <avagin@google.com>
- Formalize Master and Slave descriptor roles
- Explain the SCM_RIGHTS distribution mechanism
- Document transport socket naming and 'criu_run_id' usage
- Detail deterministic master selection to avoid deadlocks
- Explain dynamic service FD relocation during collisions
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the challenges of finding the 'watchee' path
- Explain the use of open_by_handle_at() and Irmap
- Explicitly document that pending events are dropped with a warning
- Explain how spurious events are generated during restore (ghost files)
- Add details for Fanotify inode and mount marks
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the PTRACE_SEIZE and PTRACE_INTERRUPT sequence
- Detail the transparency of ptrace-stop (TRAP_STOP)
- Document cgroup v1 and v2 freezer mechanisms
- Mention kernel kludges for v1 freezer unreliability
- Clarify the relationship between freezer and ptrace
Signed-off-by: Andrei Vagin <avagin@google.com>
- Formalize TASK_ALIVE, TASK_STOPPED, and TASK_DEAD states
- Explain the rationale for default behaviors in dump/restore
- Mention pre-dump enforcement of the Running state
- Document the use of --leave-stopped for debugging
- Add instructions for resuming trees via SIGCONT and pstree_cont.py
Signed-off-by: Andrei Vagin <avagin@google.com>
- Formalize the Master and Slave descriptor concepts
- Describe the 'open()' state machine and early FD distribution via SCM_RIGHTS
- Document the inter-process synchronization (set_fds_event, futexes)
- List key dependencies (TTYs, Unix Sockets, Epoll)
- Add notes on Service FDs and restoration ordering
Signed-off-by: Andrei Vagin <avagin@google.com>
- Detail the Linux file object hierarchy (Inode, Dentry, File)
- Explain the SCM_RIGHTS mechanism for retrieving local FD copies
- Describe the gen_id and kcmp optimization for shared file detection
- Clarify the two-tier image storage structure (fdinfo vs specialized images)
Signed-off-by: Andrei Vagin <avagin@google.com>
- Formalize the architectural comparison (userspace vs. kernel integration)
- Highlight the dangers of DMTCP's fake PID virtualization
- Explain CRIU's usage of ns_last_pid and clone3 for real PID restoration
- Improve overall technical clarity and structure
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the identification of COW candidates by comparing parent/child VMAs
- Describe the pre-mapping strategy before fork to leverage kernel sharing
- Detail the content verification and manual COW triggering
- Document the use of madvise(MADV_DONTNEED) for final memory layout accuracy
- Clarify current limitations regarding reparenting and VMA movement
Signed-off-by: Andrei Vagin <avagin@google.com>
- Embed DMTCP description and characteristics
- Update CRIU supported architectures (s390, MIPS, RISC-V, etc.)
- Refine the comparison table for accuracy and modern features
- Add more context for BLCR, PinPlay, and Legacy OpenVZ
Signed-off-by: Andrei Vagin <avagin@google.com>
- Document the use of 'compel hgen' for header generation
- Update the example header format to include structured relocations
- Describe the 'parasite_blob_desc' setup functions
- Refine the build procedure steps
Signed-off-by: Andrei Vagin <avagin@google.com>
- Clarify freezing mechanisms (PTRACE_INTERRUPT, Freezer CGroup)
- Detail the parasite injection and bootstrap process
- Explain the role of the restorer blob as a PIE and its conflict avoidance
- Document the final transition via sigreturn
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain the core problem of TCP 4-tuple mismatch
- Describe solutions for listening, in-flight, and established sockets
- Document the UPDATE_INETSK plugin hook for programmatic IP remapping
- Add a summary table of options and flags
Signed-off-by: Andrei Vagin <avagin@google.com>
- Document full CGroup v2 support and properties
- Explain CGroup namespace (CLONE_NEWCGROUP) handling
- Clarify the 'soft mode' default and other restoration strategies
- Detail the root mount requirement for bind-mounted subgroups
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain metadata collection from /proc and BPF syscall
- Describe data serialization using batch operations
- Add details about frozen maps handling
- Clarify current limitations regarding map_extra and BTF
Signed-off-by: Andrei Vagin <avagin@google.com>
- Explain how CRIU restores AIO context IDs and ring buffers
- Describe the tail synchronization technique using dummy /dev/null requests
- Clarify the lack of support for in-flight events and its implications
Signed-off-by: Andrei Vagin <avagin@google.com>
- Replace FIXME with a detailed description of the current approach
- Explain architecture detection using PTRACE_GETREGSET
- Describe the restoration process via sigreturn and mode switching
- Update vsyscall handling details
- Clarify the status of x32 support and TIF_IA32 removal
Signed-off-by: Andrei Vagin <avagin@google.com>
Private anonymous VMA contents have to be copied inside the PIE
restorer after mappings are placed at their final addresses.
Replace the synchronous preadv loop with a bounded Linux native AIO
window that submits page-read iovecs, reaps completions, and
resubmits short reads.
Keep auto-dedup punching on completed byte ranges and tear down the
AIO context on both success and error paths. The pages fd is
prepared for O_DIRECT before entering the restorer.
VMA page reads are page-aligned by construction: the destination
buffers are page-aligned, the iovec lengths are page multiples, and
the file offsets are page-aligned. O_DIRECT completions are
therefore always a whole number of pages (short reads only occur at
MAX_RW_COUNT or at EOF on page-multiple files), so resubmitting a
short read keeps its offset and buffers aligned without masking the
completion length.
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-opus-4-7
Assisted-by: Codex:gpt-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Shared-memory restore currently issues page reads one pagemap entry
at a time. Use the existing PR_ASYNC path to enqueue shmem and
memfd-shmem reads, then flush each batch with one async-queue sync
pass.
Restore shmem, sysv-shmem and memfd-shmem content through a single
flat do_restore_shmem_content() loop that owns its page_read, and
map the memfd the same way as anonymous shmem so both share one
restore path instead of an extra temporary mapping.
Shmem segments are mapped via mmap() (page-aligned addresses) and
the pagemap offsets are PAGE_SIZE multiples, so the batched reads
are page-aligned and need no special O_DIRECT alignment handling.
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-opus-4-7
Assisted-by: Codex:gpt-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
Native AIO page restore needs the pages image fd to support direct
I/O, but some filesystems accept O_DIRECT with fcntl() and reject
the first read with EINVAL.
Enable O_DIRECT after the image headers are read, probe with an
aligned read, and fall back to buffered sequential I/O when the
probe reports EINVAL. Cache the result in page_read so normal page
reads do not need a flag lookup per request.
The streamer fd (opts.stream) is excluded from the probe because
its read loop uses arbitrary user buffers that are not aligned for
O_DIRECT.
PAGE_SIZE is not a compile-time constant on aarch64 (sysconf-backed
runtime value to support 4K/16K/64K kernels), so the probe buffer
is allocated with posix_memalign() instead of a stack array with
__attribute__((aligned(PAGE_SIZE))).
The single-page COW comparison buffer in restore_priv_vma_content()
is likewise allocated with posix_memalign() so direct reads into it
are page-aligned; this lets the local read path drop its per-read
bounce buffer.
Assisted-by: Claude:claude-sonnet-4-6
Assisted-by: Claude:claude-opus-4-7
Assisted-by: Codex:gpt-5
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
The restorer already has io_setup, io_submit, and io_getevents
syscall wrappers for all supported architectures. Native AIO restore
also needs io_destroy to release the AIO context before leaving the
restorer path.
Add the missing io_destroy syscall entries next to the existing
native AIO syscalls.
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Dan Feigin <dfeigin@nvidia.com>
The alpine-test CI job runs all ~483 zdtm tests sequentially three
times (normal, mntns-compat-mode, criu-config), followed by many
non-shardable tests. This dominates overall CI wait time. With only
2 jobs running in parallel (GCC and CLANG) the alpine tests take
around 30 minutes.
Use the existing --test-shard-index and --test-shard-count flags
already built into test/zdtm.py to split the zdtm test suite across
four parallel runners (shards 0-3). A fifth shard runs all
non-shardable tests (lazy pages, fault injection, test/others/*,
rootless, compel, plugins, etc.) independently and in parallel with
the zdtm shards. This increases parallelism from 2 to 10 jobs and
reduces the alpine test wall-clock time from ~30 to ~10 minutes.
Changes:
- run-ci-tests.sh: Build SHARD_OPTS from ZDTM_SHARD_INDEX/COUNT
env vars and pass them to zdtm.py. Extract all non-shardable
tests into a run_non_shardable_tests() function. Dispatch based
on shard index: 0-3 run zdtm slices, 4 runs non-shardable
tests, unset runs everything sequentially (preserving existing
behavior). Validate that ZDTM_SHARD_INDEX is set when
ZDTM_SHARD_COUNT is set.
- Makefile: Pass ZDTM_SHARD_INDEX and ZDTM_SHARD_COUNT into the
container when set. Split long container run command across
multiple lines for readability.
- ci.yml: Add shard: [0, 1, 2, 3, 4] to the alpine-test matrix,
producing 10 jobs (2 compilers x 5 shards). Job labels now show
descriptive shard names (e.g. "zdtm 1/4", "non-zdtm") instead
of raw indices.
When sharding is not configured the script behaves identically to
before, so other CI jobs (aarch64, compat, gcov, etc.) are
unaffected.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Starting with Linux 7.1, the kernel enforces strict read-only field
protection for the rseq V2 ABI. Userspace is no longer allowed to
modify kernel-managed fields (cpu_id_start, cpu_id, node_id, mm_cid)
while rseq is registered. Violations are detected on the next context
switch and the offending process is killed with SIGSEGV.
The rseq01 test was zeroing the entire glibc-registered rseq area
with memset() before calling test_init(), which internally calls
fork(). This corrupted the read-only fields while the glibc rseq
registration was still active, causing the kernel to send SIGSEGV
during the fork.
Fix this by calling unregister_old_rseq() before the memset in both
main() and thread_routine(), so the kernel is no longer monitoring
those fields when they are zeroed. The subsequent register_thread()
call re-registers rseq with the clean area.
Link: 7f00232152
Assisted-by: Claude Code (https://claude.ai/code):claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Commit
1961c5e0de ("plugins/amdgpu: Cleanup env variable handling")
converted some error logs into warnings under the rationale of failures
not being fatal, but the execution continues with the default values.
Convert one more such error to a warning, as pointed out by Copilot that
makes things more consistent.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Copilot reports a possible false positive error on strtoul conversion due
errno not being reset on success. Fix it by clearing errnor prior to the
call.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Copilot reports %d is correct for boolean and %zx for size_t, fix it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Fixes: 1961c5e0de ("plugins/amdgpu: Cleanup env variable handling")
A bunch of globals defined at the top of amdgpu_plugin.c only needs local
scope so make it so.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
It is a bit tidier to make the helpers return the value instead of passing
in the pointer, so lets make them take the default and return the overall
result, allowing the call sites to consolidate into a single line.
While at it we make the helpers static since they are not used outside the
file and demote the parsing errors to warning log messages since the
plugin does continue operating.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
In restorer_get_vma_hint, if a VMA from self_vma_list or tgt_vma_list
overlaps with the current candidate region (prev_vma_end + vma_len), we
advance prev_vma_end and move to the next VMA in the list. However, we
must then restart the check from the beginning of the while loop to
ensure that the updated candidate region doesn't overlap with any other
VMAs.
Fixes#3018
Fixes: 2c9ee0abd2 ("restore: update prev_vma_end after processing the last vma in a list")
Signed-off-by: Andrei Vagin <avagin@google.com>
mmaps done just for reserving address space something like
void *addr = mmap(NULL, SIZE, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
Ensure that these do not have ac flag set in /proc/pid/smaps.
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
An application might call mmap with PROT_NONE to reserve a large amount
of the virtual address space. Something like:
void *addr = mmap(NULL, SIZE, PROT_NONE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
During restore, when we have to premap private vmas (ie pieok is false),
CRIU tries to mmap this large PROT_NONE and fails.
If a vma has never been written to, it does not have "ac" flag set. Use
this fact to safely premap vmas that were done for address reservation.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Here is actually two issues:
First, prev_vma_end isn't updated properly after processing the last vma
in a list.
Second, a dummy end_vma isn't fully initialized and vma_area_is can
access uninitilized data.
Signed-off-by: Andrei Vagin <avagin@google.com>
Linking on arm64 using lld fails with:
LINK criu/pie/parasite.built-in.o
ld: error: discarding .shstrtab section is not allowed
keep the missing sections to enhance portability
Fixes: #2978
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
building on a system without gcc fails with error:
make[1]: gcc: No such file or directory
use system default cc to enhance portability
fixes: #2976
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
Add tests for pre-dump, dump, and restore workflow using the loop
workload, a shell-job test with PTY setup, and a service test that
exercises the full workflow through a criu service daemon.
Pre-dump tests are skipped on architectures without soft-dirty page
tracking (e.g. aarch64). Only dump/restore are tested on these cases.
To help with CI debugging, the CRIU log files are shown on test failure.
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Add a reference C client that uses libcriu to checkpoint and restore
processes. Set LOCAL=0 to build against the system-installed libcriu
instead of the source tree.
Status messages use fprintf(stderr) so they are not delayed by stdout
buffering when running without a terminal (e.g. in CI).
Assisted-by: Claude:claude-opus-4-7
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Starting with Linux kernel commit 7b735ef81286 ("rtnetlink: add
missing netlink_ns_capable() check for peer netns"), creating a
veth pair with a peer in a different network namespace requires
CAP_NET_ADMIN in the peer namespace as well:
rtnetlink: add missing netlink_ns_capable() check for peer netns
rtnl_newlink() lacks a CAP_NET_ADMIN capability check on the peer
network namespace when creating paired devices (veth, vxcan,
netkit). This allows an unprivileged user with a user namespace
to create interfaces in arbitrary network namespaces, including
init_net.
Add a netlink_ns_capable() check for CAP_NET_ADMIN in the peer
namespace before allowing device creation to proceed.
Link: 7b735ef812
When CRIU restores a veth in user namespace mode, it sends the
RTM_NEWLINK request from a netlink socket inside the child user
namespace. The veth peer is placed into the root network namespace
via IFLA_NET_NS_FD, but the child user namespace does not have
CAP_NET_ADMIN in the root namespace, so the new kernel check
rejects the request with EPERM.
Fix this by routing the veth creation through usernsd when the
peer lives in an external (host) namespace specified via the
--external veth[name] restore option. usernsd runs with real
root privileges in the init user namespace, so it passes the
capability check in both namespaces.
The usernsd path is only used for external veth mappings, not for
child-to-child namespace veths (has_peer_nsid), because in that
case both namespaces share the same user namespace and already
have CAP_NET_ADMIN in each other.
The approach mirrors restore_one_macvlan(), which already solves
the same CAP_NET_ADMIN-in-both-namespaces problem for macvlan
devices. A new veth_link_info_userns() builds the RTM_NEWLINK
request without IFLA_NET_NS_FD for the peer -- since usernsd
sends the request from the root network namespace, the peer
naturally stays there. userns_restore_one_link() then adds a
top-level IFLA_NET_NS_FD to move the main device into the child
namespace.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
Protobuf 7.x (shipped in Arch Linux) removed the `label` instance
attribute from `FieldDescriptor`. Accessing `field.label` now
raises `AttributeError`, which breaks all CRIU tests at the
`check_pages_counts` step when pycriu tries to convert protobuf
stats images to dicts:
File "test/pycriu/images/pb2dict.py", line 345, in pb2dict
if field.label == FD.LABEL_REPEATED:
AttributeError: 'FieldDescriptor' object has no attribute 'label'
Protobuf 7.x replaced `field.label` with boolean properties
`field.is_repeated` and `field.is_required`. These properties
do not exist in protobuf 3.x/4.x.
Add a `_is_repeated()` compatibility helper that checks for the
`label` attribute first (protobuf <= 5.x) and falls back to
`is_repeated` (protobuf >= 7.x), keeping pycriu working across
both old and new protobuf versions.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
Starting with Linux 7.0, the rseq feature size has grown to 33 bytes
and AT_RSEQ_ALIGN has increased to 64. This causes sizeof(struct rseq)
from the uapi header to be 64 (33 bytes padded to aligned(32)), while
the actual registration size used by glibc (__rseq_size) is 33.
The rseq01 test was using sizeof(struct rseq) as the registration
size and a test-local __rseq_abi variable (with only 32-byte
alignment from the uapi header) as the rseq area. Both are
wrong on kernel 7.0:
- The kernel now checks alignment against __alignof__(struct rseq)
which is 64 internally; the 32-byte-aligned test variable may
not satisfy this.
- sizeof(struct rseq) = 64 does not match the feature size of 33
that glibc registered with, so re-registration with a different
size fails.
Fix by:
- Using __rseq_size (the feature size reported by glibc) as the
registration size instead of sizeof(struct rseq).
- Using the glibc-provided rseq area (at thread_pointer() +
__rseq_offset) which is allocated with proper AT_RSEQ_ALIGN
alignment, instead of a test-local variable.
Both fall back to the previous behavior when glibc rseq support
is not available.
This mirrors the glibc fix:
https://sourceware.org/cgit/glibc/commit/?id=67f303b47dc584f204e3f2441b9832082415eebc
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
Kernel 7.1 removed IPPROTO_UDPLITE support. Add a checkskip
script that probes for a UDPLITE socket and skips the test
with EPROTONOSUPPORT instead of failing.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
Refactor lima.sh to extract shared helpers (_common_setup and
_common_test) and add a second variant that uses the
@kernel-vanilla/next COPR repository. Convert the Lima CI job
to a matrix with both stable and next variants so we catch
upstream kernel changes (such as the UDPLITE removal in 7.1)
early.
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
Kernel 7.1 removed IPPROTO_UDPLITE support. When the UDPLITE diag
module is absent, the netlink request returns -ENOENT, which CRIU
was treating as a fatal error causing the entire dump to fail.
Apply the same treatment as IPPROTO_RAW: return success from the
error callback so the dump can proceed. If a UDPLITE socket is
actually encountered, it will fail at lookup time with a clear
error rather than failing the entire dump preemptively.
Fixes: https://github.com/checkpoint-restore/criu/issues/3002
Assisted-by: Claude Code (claude-opus-4-6):claude-opus-4-6@default
Signed-off-by: Adrian Reber <areber@redhat.com>
Mostly after calling libdrm functions pr_perror is wrong because calling
convention there is to return zero or negative error code - errno is not
guaranteed to be valid. So convert those to pr_err with manually calling
strerror to log user friendly messages. Same conversion for handling
errors from some plugin internal functions.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com> # v1
Cc: Radostin Stoyanov <rstoyanov@fedoraproject.org>
---
v2:
* Handle newly added pr_perror after amdgpu_device_initialize().
* Add newlines.
v3:
* Add some newlines to pr_err.
There is no need to initialize and de-initialize libdrm only to use the
duplicated fd for calls to drmPrimeFDToHandle(). From the kernel's
perspective it is exactly the same file so operation is identical to just
using the passed in file descriptor.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Consolidate KFD and DRM VMA handling path to the same (existing) helper.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Only try to restore the dmabuf fd if the render node restore failed due
image not present. Other errors means the file is a render node (image is
present) so we can return an error straight away.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Currently the code contains multiple places where callers expect the errno
to be valid (implied by calling pr_perror to log file IO errors) after
calling open_img_file(), read_fp() and write_fp() helpers. Problem there
is that those helpers can destroy the errno courtesy of themselves
emitting log messages via fprintf.
Furthermore, the callers then sometimes invent the errors to return back
to the caller, or even outside of the plugin.
On top of that there is no benefit to buffered file IO given the plugin
reads and writes in buffer object size chunks, so it it preferrable to
just go direct and avoid any possibility of extra copying to and from libc
temporary buffers.
So lets just convert it all in one swoop to POSIX IO and make sure correct
errnos are always propagated to the caller (including to CRIU core).
Hopefully this removes all instances of incorrect pr_perror log messages.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com> # v1
---
v2:
* Handle short reads and writes.
* Add O_TRUNC.
v3:
* Handle EINTR and EAGAIN.
* Set errno on len == 0.
* Use %zu for size_t printing.
v4:
* Drop shadowed ret.
* Drop needless casts.
Use the recently added image load helper in one more function which
contains the exactly same flow of open-alloc-read.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Given that dump and restore of KFD vs DRM forks into completely parallel
flows inside the respective plugin callbacks, lets split it out by
extracting into helpers. This de-clutters the code flow and makes it
obvious which part is done where.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Currently the plugin is added to the inventory only if there were amdgpu
mapped vmas in the target process. This makes restoring a simple process
with only an open DRM fd and some buffer objects not work.
Fix it by adding the plugin to the inventory when there were open DRM
files as well.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Check SDMA operation type once at the beginning of the copy helper and fix
one incorrect usage of pr_perror while at it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Open_drm_render_device() is a little bit confused. It can log confusing
errors using errno which hasn't been set, or it has been overwritten. It
can also inspect errno after it had reset it creating effectively
unreachable code. And finally it sometimes returns the negative errno, and
sometimes a plain -1. Fix it all up and make it consistent, while at the
same time correcting two calls site incorrectly using pr_perror(), while
the function does not guarantee a valid errno.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Error logging for just a single error condition will eat the errno so lets
just remove it. All callers use pr_perror() and rely on the helper not
munching it up so no information is lost by removing the internal log.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
We remove some function entry and exit markers, some interim messages
which provide no real value, and only log virtual address allocation
failures on the failure path. For the last one we also fix incorrect
usage of pr_perror.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
The extra debug build log helper does not seem very useful and some of
them do not even compile. Lets just remove it and replace with the
standard pr_debug. In case of too much noise, we can later re-evaluate
to remove some of the not very useful log messages.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Instead of open coding the same ioctl twice we can put it in a loop from
which we break out once we have allocated enough space for all objects.
While at it we add error handling for the memory allocation.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
---
v2:
* s/for(;;)/while(1)/ (David)
Both CRIU and plugin are built with 64-bit off_t and most of the parallel
bo restore path uses uint64_t for storing offsets.
Lets consolidate by changing int to off_t, and by doing so remove any
possibility that the call to fseeko can overflow the return type.
While at it, add error checking to both seek operations.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com> # v1
---
v2:
- Correct offset type as well.
Shallower indentation makes a heavily indented function hopefully a bit
more readable.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Consolidate to one fclose() call with the extra bonus the inconsequential
file descriptor leak is eliminated.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Close the directory when probing images during restore init fails.
While at it, consolidate the identical code between the DRM and KFD images
into a common helper.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Currently the failure to save content of a buffer object is only logged,
while the checkpointing will continue unaware due the error code being
"eaten" inside sdma_copy_bo() cleanup path, together with the caller not
checking the return value to begin with.
Fix it by preserving and returning the original error code inside
sdma_copy_bo(), and abort the checkpointing process in case of a failure.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Currently failure to open files logs an unitialized stack string as the
failed path. Lets just log the basename and drop the unused stack buffer.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Size needs to be initialized before opening the file for write, otherwise
garbage is written into the file.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
The new_minor field in struct vma_metadata is effectively unused.
Remove it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Remove unused current_pid global variable.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Instead of logging a zero failure code lets log the actual GPU id which
was not found.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-By: David Francis <David.Francis@amd.com>
Check that the image unpacking worked before deferencing the returned
pointer during plugin init in order to fail gracefully.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Allocate shared memory for the whole struct shared_handle_ids and not just
for the pointer to it, and by doing so stop relying on mmap rounding up to
page size.
While at it add error checking that the allocations actually succeeded.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Adjusted object sizes need to be used to unmap on the cleanup path so that
the unmap operations match with map for the case sizes were adjusted in
the function prologue.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
---
v2:
* Improve commit message and use adjusted size in error logs too.
The function was not closing the drm fd duplicated by the libdrm call,
could attempt to deinitialize the libdrm device which wasn't successfully
openened, and was using errno based log functions when libdrm functions
used return a negative errno. Fix it all.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Close the file when either memory allocation or a file read fails in
amdgpu_plugin_dmabuf_restore.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Docstring refers to size_t as 8-byte value while in reality this is
architecture dependent. Clarify it.
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
In open_path(), when inherit_fd_lookup_id() returns negative for an
external file, execution silently falls through to the normal open
path causing an incorrect size mismatch error. Added a pr_warn() to
make the failure explicit.
Fixes: #2951
Signed-off-by: Cameron Badman <cbadwork@gmail.com>
obj->frozen is uint32_t. scanf() must use the matching SCNu32 macro for
this destination type.
Use SCNu32 in parse_bpfmap_fdinfo() for the frozen field parsing.
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
The logic in sb_opt_cb converts uid and gid to using userns map, it
means that the option string can extend. Worse case we had original id
"0" and got INVALID_ID ("4294967295") back.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Build sysctl payloads with snprintf() and check for error/truncation before writing.
Use the returned payload length for write() instead of fixed-size writes, so only formatted bytes are written.
On snprintf failure/truncation, print an explicit error message and return -1. On write/open helper failures, return -1 because callers only use success/failure and pr_perror() already logs errno.
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
rand_ipc_sysctl() and rand_ipc_sem() returned on write() failure
without closing the opened sysctl fd first.
Close fd in both error paths before returning.
Also return a generic failure code (-1) in these helper paths instead of
propagating errno after close(), because close() may modify errno and
callers only use the return value as success/failure.
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
check_map_is_there() parses %x:%x major/minor fields from /proc/self/maps.
Store these values in unsigned int variables to match the "%x" specifier
and keep the parser warning-free.
Keep the end-address fragment as %*x to avoid gnu_scanf
"assignment suppression + length modifier" -Werror failures.
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
shared->opt_files and loop index i are size_t values. Printing them with
"%lu"/"%d" is type-mismatched and can produce incorrect output on some
platforms.
Switch these sites to "%zu" in logging and path formatting.
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
sb_opt_cb() parses gid=/uid= option values into unsigned id values and
passes mapped userns_*() results to sprintf(). Using "%d" for these
unsigned values is a format/type mismatch.
Switch gid=/uid= parsing and printing to "%u".
In parse_fdinfo_pid_s(), EventpollTfdEntry.tfd is uint32_t, so parse it
with SCNu32 instead of "%d" to match the destination type.
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
When bfd is unbuffered, bwritev() used writev() directly, which can return
partial writes and leave checkpoint images incomplete.
Fix this by retrying writev() until all iovecs are written or an error occurs.
Temporarily modify the first iovec's base and length to track progress on
partial writes, then restore it before the next iteration.
Changes the function signature to accept non-const iovec, as we need to
modify it to track progress (same pattern as write_all() with buffers).
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Currently, bfd has a fixed buffer size (BUFSIZE, which is 4096). This
causes issues when reading lines longer than BUFSIZE, as breadline
fails with "The bfd buffer is too small".
This patch introduces dynamic buffer resizing in bfd. When a buffer
is full and more space is needed (e.g., for a very long line), the
buffer is resized using mremap (or a new mmap if it was using a
pre-allocated buffer from the pool).
A new bsize field is added to struct xbuf to keep track of the
current buffer size.
Unit tests for reading long lines and writing large buffers are
added to criu/unittest/unit.c.
Signed-off-by: dong sunchao <dongsunchao@gmail.com>
Co-developed-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
In amdgpu_plugin_drm_restore_file(), dmabuf_fd can reach the
drmPrimeFDToHandle() call as -1 if fdstore_get() fails or if
boinfo->handle is -1 while boinfo->is_import is true. Passing
an invalid fd to libdrm causes a hard restore failure instead
of a retry. Check for -1 and set retry_needed so the restore
coordinator can retry later.
When retry_needed is set, some dmabufs entries are still invalid,
so skip record_completed_work() and restore_bo_contents_drm()
to avoid operating on incomplete state.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Several error paths in amdgpu_plugin_drm_dump_file() leak
resources. The drmPrimeHandleToFD() and open_img_file() failures
use break instead of goto exit, which skips per-iteration cleanup
and lets the function continue dumping metadata with a stale ret
value. Replace break with proper resource cleanup and goto exit.
The vm_info_entries buffer is not freed when the ioctl or
allocate_vm_entries() calls fail after allocating it, and the
buffer from posix_memalign() is never freed after sdma_copy_bo(),
leaking memory on every loop iteration. Add the missing xfree()
calls.
Check the amdgpu_device_initialize() return value because h_dev
is undefined on failure. Move list_handles_entries cleanup into
the exit block because error paths that goto exit skip the
existing xfree() call after the loop. Add a NULL check before
free_e(rd) because rd allocation can fail before the struct is
initialized.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Initialize gpu_ids, fds_write, and entries to NULL before
allocating them in init_parallel_restore_cmd() and
init_parallel_restore_cmd_by_head(). The caller declares the
struct on the stack without an initializer, so these members
hold undefined values. If a later xzalloc() fails and the
caller invokes free_parallel_restore_cmd(), it will call
xfree() on those undefined pointers.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Call amdgpu_device_deinitialize() before continuing when
get_gem_handle() fails and before returning when a matching
handle is found. Both paths skip the existing deinitialize
call at the end of the loop body, leaking the device handle.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
open_img_file() can return NULL after a read_fp() or write_fp()
failure without setting errno. The openat() and fdopen() paths
set errno, but the read/write path does not, so callers using
-errno get zero or a stale value. Set errno to EIO on this path
so errno is always valid when the function returns NULL.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Close the file descriptor when fdopen() fails, as fdopen does not
take ownership of the fd on failure.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The exit label in amdgpu_plugin_drm_restore_file() returns
immediately when ret < 0 without freeing the dmabufs array or
deinitializing the amdgpu device handle. Move cleanup before the
error check so resources are always released.
Replace xzalloc() with xmalloc() and memset(0xff) for the dmabufs
array because zero is a valid fd number and would cause the cleanup
loop to close fd 0 (stdin) for unpopulated entries. Initializing
to KFD_INVALID_FD (0xffffffff) lets the exit block tell which fds
were actually opened. Guard amdgpu_device_deinitialize() behind a
dev_initialized flag to avoid calling it when initialization failed,
and close dmabuf_fd when drmPrimeFDToHandle() fails. To prevent
double-closing fds that restore_bo_contents_drm() already closed,
only run the close loop when the BO content restore was not reached.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Free the protobuf message and buffer when returning early from
amdgpu_plugin_dmabuf_restore() on failure to find a dmabuf fd.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
posix_memalign() returns an error code on failure and does not
guarantee setting the pointer to NULL. Check the return value
instead of the pointer. Since posix_memalign() does not set
errno, assign it explicitly so pr_perror() prints the correct
message. Negate the return code instead of hardcoding -ENOMEM
to preserve the actual error (e.g. EINVAL for bad alignment).
In amdgpu_plugin_drm_dump_file(), replace break with cleanup
and goto exit so per-BO resources are freed on failure.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When parse_threads() is called with a pre-allocated array (e.g., when
re-parsing threads), it must ensure that the number of threads found in
/proc does not exceed the size of the provided buffer. Add a check to
prevent out-of-bounds access if the thread count increases unexpectedly.
Signed-off-by: Andrei Vagin <avagin@google.com>
The exit status in the wait status word is 8 bits. Using a 0x7f mask was
incorrectly stripping the highest bit of the exit code. Use 0xff mask
instead to correctly preserve the full 8-bit exit status.
Signed-off-by: Andrei Vagin <avagin@google.com>
When writing numeric values to /proc files (like oom_score_adj, loginuid,
and pid_max), we were using hardcoded lengths or full buffer sizes in
write() calls. This could result in writing garbage characters from the
stack if the actual string was shorter than the specified length.
Use the length returned by snprintf() to ensure only the intended string
is written. Also, increase the buffer size for oom_score_adj to avoid
truncation.
Signed-off-by: Andrei Vagin <avagin@google.com>
mmap() returns MAP_FAILED ((void *)-1) on failure, not NULL. Checking
for NULL is incorrect and would miss actual failures, leading to
potential null pointer dereferences later.
Signed-off-by: Andrei Vagin <avagin@google.com>
siginfo_priv_nr was allocated in prepare_siginfo_priv() but never
freed. Add an xfree() call in sigreturn_restore() to clean it up.
Also, remove an incorrect attempt to free thread core entries inside the
main thread loop in sigreturn_restore(), as these are now properly
handled at the end of the function.
Signed-off-by: Andrei Vagin <avagin@google.com>
In open_cores(), we were not freeing already opened core entries if one
of them failed to open. Also, the cores array was not zero-initialized,
which could lead to freeing garbage pointers in the error path. Use
xzalloc() to ensure the array is zeroed.
In sigreturn_restore(), thread core entries were not being freed after
use, leading to a memory leak. Add a loop to free them.
Signed-off-by: Andrei Vagin <avagin@google.com>
The aarch64 Fedora Rawhide test has been moved to GitHub Actions
as part of the fedora-rawhide-test matrix build. Remove it from
the Cirrus CI configuration.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Convert the fedora-rawhide-test job to a matrix build that runs
on both ubuntu-22.04 (x86_64) and ubuntu-24.04-arm (aarch64).
This replaces the aarch64 Fedora Rawhide build-only test
previously running on Cirrus CI with a full test run on GitHub
Actions.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Remove leftover pidfile and criu_service.socket at the start of
the run target. If these files exist from a previous interrupted
run, the service fails to start and read.py hangs forever waiting
on the status fifo.
Acked-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Verify that the page server binds to the address given in
the RPC request when lazy_pages is enabled. Without the fix
in the previous commit, the address was silently ignored and
the page server would bind to 0.0.0.0 instead.
The test sends a PAGE_SERVER request with ps.address set to
127.0.0.1 and lazy_pages enabled, then checks /proc/net/tcp
to confirm the page server actually bound to that address.
Acked-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The page server address from RPC requests was ignored when
lazy_pages was enabled. The code that copies the address into
opts.addr only ran inside the !opts.lazy_pages branch, so with
lazy pages the page server would bind to 0.0.0.0 instead of
the specified address.
This breaks live migration when the container runtime needs the
page server to listen on a specific address. The zeropod project
worked around this with a downstream patch that adds a raw
pointer assignment (opts.addr = req->ps->address), but that
causes a use-after-free when the protobuf message is freed.
Fix this by moving SET_CHAR_OPTS (which copies via strdup) and
the NULL fallback outside the !opts.lazy_pages block so they
apply unconditionally.
Reproducer (run as root, requires pycriu):
sleep 99999 &
criu dump -t $! -D /tmp/imgs --shell-job -v0
criu service --address /tmp/criu.sock -v0 &
python3 -c "
import os, socket
from pycriu import rpc_pb2 as rpc
s = socket.socket(socket.AF_UNIX, socket.SOCK_SEQPACKET)
s.connect('/tmp/criu.sock')
req = rpc.criu_req()
req.type = rpc.PAGE_SERVER
req.opts.images_dir_fd = os.open('/tmp/imgs', os.O_DIRECTORY)
req.opts.lazy_pages = True
req.opts.ps.port = 27
req.opts.ps.address = '127.0.0.1'
s.send(req.SerializeToString())
"
ss -tlnp sport = :27 # Bug: shows 0.0.0.0:27 instead of 127.0.0.1:27
Acked-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Add a test that verifies pipe ownership (uid/gid) is preserved across
checkpoint/restore. This test exercises the fix for issue #2984 where
accessing pipes via /proc/self/fd/ failed after restore because the
pipe ownership was changed to root.
The test:
- Creates a pipe and optionally changes ownership (if running as root)
- Records ownership before C/R
- Verifies ownership is preserved after restore
- Tests /proc/self/fd access works after restore
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
When CRIU runs as root and restores a pipe, the pipe inode is created
with root ownership. If the restored process runs as a non-root user
and tries to reopen the pipe via /proc/self/fd/<n>, the open() fails
with EACCES because the pipe inode is owned by root.
Fix this by saving the pipe's uid/gid during dump (from stat) and
restoring ownership with fchown() after creating the pipe. This
matches how memfds and TTYs already handle ownership restoration.
Fixes: #2984
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Cirrus CI reports "Failed to start an instance:
FAILED_PRECONDITION: Monthly compute limit exceeded!" making the
Vagrant Fedora Rawhide test unusable.
Replace the Cirrus CI Vagrant-based Fedora Rawhide test with a
Lima VM-based equivalent in GitHub Actions. This follows the same
pattern used by the runc project (lima-vm/lima-actions).
The new vagrant-fedora-rawhide-test job:
- Starts a Lima Fedora VM with KVM acceleration
- Installs the latest vanilla kernel
- Reboots the VM to activate the new kernel
- Runs the fedora-rawhide CI target inside a podman container
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
The --pids-limit=0 value does not disable the pids limit in
current podman versions. The podman documentation specifies
that -1 means unlimited. With --pids-limit=0, the thread-bomb
test fails on the second run (after restore) because each of
the 1024 threads tries to create a new thread, exceeding the
container's pids limit and causing pthread_create() to return
EAGAIN.
Change --pids-limit=0 to --pids-limit=-1 to properly disable
the pids cgroup limit.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
struct parasite_ctl, parasite_thread_ctl, and plain_regs_struct
all contain user_fpregs_struct_t (typedef for struct xsave_struct),
which is declared with __aligned(64). When these structs are
allocated on the heap with xmalloc/xzalloc (i.e. malloc/calloc),
the allocator only guarantees 16-byte alignment on x86_64.
The compiler, seeing the __aligned(64) attribute on the struct
type, may emit aligned memory instructions (e.g. movaps, vmovdqa)
for struct copies, assuming the memory is properly aligned. When
the heap pointer is not 64-byte aligned, these instructions trigger
a General Protection Fault (#GP).
This was observed as a crash in save_regs_plain() at infect.c:1314
(prs->regs = *r) on CentOS Stream 10 under QEMU/KVM, where the
compiler generated aligned vector instructions for the struct copy.
The crash did not reproduce on bare metal with a different compiler
version that happened to emit unaligned instructions.
Add xmemalign() wrapper around posix_memalign() to xmalloc.h and
use it for all three allocation sites:
- compel_prepare_noctx(): struct parasite_ctl
- compel_prepare_thread(): struct parasite_thread_ctl
- compel_prepare(): struct plain_regs_struct
Memory from posix_memalign() can be freed with free(), so no
changes to cleanup paths are needed.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
The control message buffer was hardcoded to 1024 bytes, which is
insufficient for the kernel's maximum allowed file descriptor count.
SCM_RIGHTS can carry up to 253 file descriptors, requiring
CMSG_SPACE(253 * sizeof(int)) = 1032 bytes. Additionally, a single
packet can carry multiple SCM types (SCM_RIGHTS, SCM_CREDENTIALS,
SCM_PIDFD), pushing the worst case to ~1088 bytes.
Increase the buffer to 2048 bytes for safety.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Wire riscv64 CRIU core data into the Python coredump generator.
Set EM_RISCV in the ELF header, map GP registers for NT_PRSTATUS,
map FP registers for NT_FPREGSET, and enable the existing smoke test
on riscv64.
The layout follows the current CRIU riscv64 core format and the
Linux RISC-V user ABI.
Partially addresses #2433.
Signed-off-by: Shaurya Rane <ssrane_b23@ee.vjti.ac.in>
Add a ZDTM test for the timer_slack_ns checkpoint/restore feature.
The test sets a custom timer slack value (123456789 ns) before C/R
and verifies it is preserved after restore.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
During restore, set the per-thread timer_slack_ns value via
PR_SET_TIMERSLACK if the image contains it. This completes the
checkpoint/restore cycle for the timer slack property.
The restore is skipped for images that do not contain the field,
maintaining backward compatibility with older image formats.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Collect the per-thread timer_slack_ns value from each thread via
PR_GET_TIMERSLACK in the parasite and store it in the thread core
image entry.
PR_GET_TIMERSLACK returns the slack value directly as a long, so a
separate long variable is used to avoid truncation when storing the
result.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Add optional uint64 timerslack_ns field (= 17) to thread_core_entry.
This allows CRIU to save and restore the per-thread timer slack value
(controlled via PR_SET_TIMERSLACK / PR_GET_TIMERSLACK) across
checkpoint/restore cycles.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Add an "AI-assisted contributions" section to CONTRIBUTING.md
describing the Assisted-by tag format for commits that involve
AI coding assistants, following the Linux kernel guidance at
docs.kernel.org/process/coding-assistants.html.
Also add concise instructions to GEMINI.md (symlinked to
CLAUDE.md) so that AI agents use the Assisted-by tag instead
of free-form attribution lines.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Add a test that exercises the broken read lease restore path. The test:
1. Opens a file O_RDONLY and takes a read lease (F_RDLCK).
2. Triggers the breaking sequence by attempting a conflicting
O_WRONLY | O_NONBLOCK open (which returns EWOULDBLOCK).
3. Forks a child to verify post-restore lease state.
4. Calls test_daemon() / test_waitsig() to go through C/R.
5. After restore, the child verifies that the lease type is F_UNLCK
(the expected target type for a broken read lease), confirming
that the breaking sequence was correctly re-established.
Without the preceding fix, restore_lease_prebreaking_state() would set a
write lease (F_WRLCK) instead of a read lease on the read-only fd,
causing either a restore failure (EACCES) or a wrong lease type
post-restore. This test fails without the fix and passes with it.
Signed-off-by: Andrei Vagin <avagin@google.com>
When restoring a breaking lease, CRIU needs to first restore the
pre-breaking state of the lease and then trigger the break again.
Previously, restore_lease_prebreaking_state() was incorrectly using the
file descriptor type (e.g., FD_TYPES__REG) instead of the lease type to
determine which lease to set. This caused it to use O_RDONLY/O_WRONLY
logic on a value that wasn't an open flag.
Fix this by:
1. Passing the target lease type (with the LEASE_BREAKING bit cleared)
to restore_lease_prebreaking_state().
2. Updating set_file_lease() to optionally suppress error messages when
a lease cannot be set (EWOULDBLOCK), which happens when we try to
guess the original lease type.
3. In restore_lease_prebreaking_state(), try to set a read lease first
if the target type is F_UNLCK. If it fails, or if the target type is
F_RDLCK, try a write lease.
This ensures that we correctly attempt to restore the original lease
type even though it's not explicitly stored in the image when it's
in the process of being broken.
Reported-by: Prateek Singh Rathour <rathourprateek8@gmail.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
When running tests in parallel (-p 2) with GCOV=1, multiple
forked processes race to create ../criu.tree. The check-then-
create pattern (os.access + os.mkdir) allows two processes to
both see the directory as missing and then both attempt mkdir,
causing FileExistsError in the second process.
Replace with os.makedirs(exist_ok=True) which handles the race
atomically.
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Adrian Reber <areber@redhat.com>
Upstream Nixpkgs shadows Google's version of the default protobufs,
which is no longer applicable given that they are copied into the
repository, and causes builds to fail.
Signed-off-by: Karim Vergnes <me@thesola.io>
This allows users to directly use the criu package declared in the flake
as a bleeding-edge substitute to the one found in Nixpkgs, and leverage
the existing NixOS testing infrastructure with their development version.
Signed-off-by: Karim Vergnes <me@thesola.io>
When the amdgpu plugin is called for restore of a file img,
we don't initially know if it's a kfd or drm file. So we first
try to open a kfd file, and if that fails, we assume it's
a drm file. That failure leads to a lot of error messages like
Error amdgpu_plugin: amdgpu-kfd-141.img: Failed to open for read
For this normal behaviour.
Add an option on open_img_file to suppress this error when
we aren't sure if the file we're trying to open exists.
Signed-off-by: David Francis <David.Francis@amd.com>
open_img_file can return null if, for example, the dump file
isn't present. Tehre were three places where this wasn't checked.
Check it.
Signed-off-by: David Francis <David.Francis@amd.com>
Default to the pure-python protobuf implementation
on Python 3.14+ when the user has not explicitly
selected a backend. This avoids known protobuf
C-extension import failures seen in some distro
packaging setups.
Fixes#2848
Signed-off-by: Farzan Aman Khan <farzanaman99@gmail.com>
archlinux:latest is a rolling-release image and pacman -Syu pulls
the latest packages on every build. Failures caused by upstream
package churn or mirror outages are beyond CRIU's control and
should not block merges.
The cross-compile job already uses continue-on-error: true for
its experimental targets; apply the same treatment to
archlinux-test.
Fixes: #2911
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
With GCOV=1, zdtm.py passes the CRIU workspace parent as an
external bind-mount into the test namespace (ZDTM_CRIU). On
restore in the uns flavor CRIU calls open_tree(OPEN_TREE_CLONE)
on that path. Because the workspace is a parent of the user
namespace mount tree, its mounts are MNT_LOCKED, and open_tree
returns EINVAL.
Fix by creating a private bind-mount of the workspace parent at
'../criu.tree' before each test run, then using that path as the
source of the bind-mount inside the ZDTM namespace (ns.c). On
restore, point the external mapping at 'criu.tree' instead of
the raw workspace path.
Because criu.tree is MS_PRIVATE and is created before any CRIU
run, cgroupfs submounts that CRIU later creates inside the
workspace (cg_yard via mkdtemp) do not propagate into it.
open_tree(OPEN_TREE_CLONE, criu.tree) therefore sees no locked
submounts and succeeds.
This replaces the earlier --work-dir workaround, which was
correct in principle but broke the RPC test path where
criu_rpc.__set_opts has no handler for --work-dir.
Fixes: #2911
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Two problems made gcov-test unreliable:
1. The gcov step ran with --max-procs 4, causing multiple gcov
processes to concurrently read and update the same .gcda files.
GCC does not protect these files against concurrent access, so
this can silently corrupt coverage data or produce
non-deterministic failures. Drop --max-procs to serialize gcov.
2. 'make codecov' curls the uploader binary from
https://uploader.codecov.io/latest/linux/codecov at job
runtime. This fails on Codecov CDN outages and on pull requests
from forks where CODECOV_TOKEN is not forwarded. Replace this
step with the pinned codecov/codecov-action@v5, which avoids
the runtime curl and handles both authenticated and
unauthenticated cases gracefully.
Fixes: #2911
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Use fully qualified image names (e.g. "docker.io/...") in Dockerfiles
instead of relying on implicit registry resolution. This makes the
registry explicit and avoids ambiguity in environments where Docker
and Podman may use different default registries.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The scripts installing dependencies are now copied and executed before
copying the full source tree. This allows to cache the dependency
installation layers as long as these scripts remain unchanged.
Previously, copying the entire repository invalidated the cache on every
source change. While our CI intentionally doesn't preserve cached layers
across independent runs, the changes in this patch help with local testing
when investigating issues.
Examples:
- sudo -E make -C scripts/ci alpine GCC=1
- sudo -E make -C scripts/ci alpine CLANG=1
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Use the new consolidated GitHub Actions workflow (ci.yml)
instead of individual workflow badges.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The check-commit target verifies that each commit builds successfully
on its own. However, without cleaning previously generated build artifacts
(e.g. auto-generated `*.o` files) this can cause the check to fail:
make[2]: *** No rule to make target 'compel/include/uapi/compel/asm/breakpoints.h', needed by 'compel/arch/x86/src/lib/infect.o'. Stop.
make[1]: *** [Makefile.compel:35: compel/libcompel.a] Error 2
To fix this, we add 'git clean -dfx' to remove all untracked and ignored
files before attempting the build.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Update the state machine to track entry and exit stages for all
syscalls, not just the target one. This allows skipping
ptrace_get_regs() calls on the exit stage of syscalls.
Signed-off-by: Andrei Vagin <avagin@google.com>
The restorer used a futex to synchronize threads right before sigreturn.
This could lead to a deadlock when compel_stop_tasks_on_syscall executes
all restored tasks/threads sequentially, allowing each to execute one
syscall per iteration. One task might wait for another one that hasn't
had a chance to run yet.
To avoid this, this patch replaces the futex with an atomic variable.
The last thread to finish the restoration process handles the final
cleanup tasks, such as closing the log and unmapping restorer memory.
Signed-off-by: Andrei Vagin <avagin@google.com>
compel_stop_on_syscall is only ever called for a single task. Simplify
its implementation by removing the 'tasks' parameter and the associated
logic for handling multiple tasks. It now takes a 'pid' directly and
waits for that specific task to exit the required syscall.
Signed-off-by: Andrei Vagin <avagin@google.com>
Hardware breakpoints were originally intended to speed up the resume process
by stopping the process at a specific point in the pie code. However, it
turned out that they don't provide a significant speedup and, in some cases,
can even slow it down. This is especially critical for hosts with a large
number of CPUs.
Hardware Breakpoint Restore Performance Benchmark
==================================================
System: Linux 6.17.0-1007-gcp x86_64
CPU: INTEL(R) XEON(R) PLATINUM 8581C CPU @ 2.10GHz
Virt: google
CRIU: Version: 4.2
Iterations per data point: 5
Threads With BP (us) Without BP (us) Diff (%)
-------- ------------ --------------- --------
>>> Benchmarking with 1 thread(s)...
1 391 326 19.9%
>>> Benchmarking with 10 thread(s)...
10 1098 695 58.0%
>>> Benchmarking with 50 thread(s)...
50 3772 2344 60.9%
>>> Benchmarking with 100 thread(s)...
100 6740 4504 49.6%
>>> Benchmarking with 500 thread(s)...
500 31382 19982 57.1%
>>> Benchmarking with 1000 thread(s)...
1000 58617 40568 44.5%
Notes:
'With BP' = hardware breakpoints enabled (current default)
'Without BP' = CRIU_FAULT=130 (FI_NO_BREAKPOINTS, uses PTRACE_SYSCALL)
Positive diff% means breakpoints are slower
Signed-off-by: Andrei Vagin <avagin@google.com>
Splitting the ptrace interrupt and wait loops allows us to send the
interrupt to all tasks and threads first, so they can start stopping in
parallel while we're still sending interrupts to the remaining ones.
This should improve restore performance for large process trees.
The redundant parse_threads calls in catch_tasks are removed as threads
are already parsed in attach_to_tasks which is called earlier.
Signed-off-by: Andrei Vagin <avagin@google.com>
When CRIU traces a large number of tasks, calling wait4(-1, ...) can
be slow because the kernel has to iterate over many tasks to find one
that has changed state. This overhead becomes significant when
thousands of tasks are involved. The time complexity of the old approach
was O(n^2) because we called wait4(-1, ...) N times, and each call
took O(N) time in the kernel.
This patch introduces compel_stop_tasks_on_syscall which takes an
array of PIDs and waits for each one specifically. This avoids the
O(N) search in the kernel's do_wait implementation and significantly
improves performance during the restore phase when many tasks are
being resumed and stopped at the rt_sigreturn syscall.
Some parallelism still exists in this approach. The loop waits for each
process to stop on a syscall, verifies it, and then lets it continue
running. While we move to wait for the next process in the array, the
previously processed ones continue their execution in parallel.
The performance profile of the bottleneck showed:
- 70.45% entry_SYSCALL_64
- do_syscall_64
- 68.29% __do_sys_wait4
- kernel_wait4
- 68.28% do_wait
- 68.26% __do_wait
- 65.69% wait_consider_task
8.71% _raw_spin_lock_irq
2.39% _raw_spin_unlock_irq
Signed-off-by: Andrei Vagin <avagin@google.com>
Commit 6b29103 adds the function read_user_ns_img to read user namespace
image. It looks up the user namespace by id. However, user namespace
can not be found because only mnt, net and pid namespaces are added to
the nsid list. The user namespace is not read from pstree ids.
This commit adds user namespace to the nsid list from the pstree ids
image.
Fixes: 6b29103 ("criu: fix double-open of userns image in --stream mode")
Fixes: #2938
Signed-off-by: Efim Verzakov <efimverzakov@gmail.com>
VMA_AREA_GUARD areas are added to the end of the vma_area_list and
are not necessarily sorted by address. pmc_fill_cache() expects
VMAs to be sorted and triggers BUG_ON() if it meets a VMA with
a lower address than the current cache window.
Since guard VMAs don't have pagemap entries and are skipped during
dump, just stop the lookahead loop when we encounter one.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
restore_userns_binfmt_misc() was opening the userns image a second
time, but criu-image-streamer rejects duplicate file requests:
criu-image-streamer Error: CRIU is requesting the image file
userns-15.img multiple times. This is not allowed to keep the
memory usage low
Fix by pre-reading the image once in a new read_user_ns_img()
helper, called from prepare_namespace_before_tasks() which runs
before the first clone(). Following the same pattern as NetnsEntry
on net namespace ids, the UsernsEntry is stored in a new 'user.e'
field on the ns_id structure for the user namespace. Both the CRIU
coordinator (prepare_userns) and the forked root task
(restore_userns_binfmt_misc) look up the ns_id and access the
entry from there -- no second open_image() call is needed.
Tested with:
sudo ./test/zdtm.py run --stream -t zdtm/static/env00 --ignore-taint
sudo ./test/zdtm.py run --stream -t zdtm/static/env00 --ignore-taint -f uns
Both pass with the fix applied.
Fixes: e6510a338a ("criu: Support binfmt_misc sandboxing")
Fixes: #2924
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Install libcriu into a local staging directory (.install/) using
'make install-lib' and reference only that directory during build
and test:
CFLAGS := -I$(INSTALL_DIR)/include/criu
LDFLAGS := -L$(INSTALL_DIR)/lib -lcriu
LD_LIBRARY_PATH=${MAIN_DIR}/.install/lib
Nothing from the non-test part of the repo is used at compile,
link, or run time.
The compile rule is also corrected to use $< instead of $^
for gcc -c.
Fixes: #2927
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
gcc doesn't report any warnings if there are two identical enums with the
same name. Actually, we wanted to detect if a specific enum is already
exists. By using a different member name in the test, we ensure that a
conflict occurs if the enum is already defined in the system headers.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Rework GitHub workflows to consolidate all test-related jobs into a
single ci.yml file. This ensures that the alpine-test job runs first,
and all other tests are executed only if it passes.
This reduces redundant triggers and provides a clear dependency path
for CI runs.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
pr_perror already appends a newline; the explicit \n in the
format string violates the lint rule and breaks CI.
Fixes: 555b257c5e77 ("plugin/amdgpu: Catch error for failure to open drm device")
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
kfd_criu_device_bucket.drm_fd is an unsigned int, so the comparison
device_bucket->drm_fd < 0
was always false.
Fix that, and also make the error message a bit more descriptive.
Signed-off-by: David Francis <David.Francis@amd.com>
Fix several memory leaks in sk-queue error handling:
- collect_one_packet(): Free pkt->data when n_scm > 1 check fails.
- collect_one_packet(): Move list_add_tail() after read_img_buf() so
that a packet with freed data is never left on the list.
- dump_scm_rights(): Free scme when dump_my_file() fails. The
allocation from xmalloc() was leaked on this error path.
- send_one_pkt(): Free pkt->scm (allocated in prepare_scms()) after
sendmsg(), alongside the existing xfree(pkt->data).
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
After recvmsg() with MSG_PEEK, dump_sk_queue() checks for MSG_TRUNC
(data truncation) but not MSG_CTRUNC (control data truncation). When
the control message buffer is too small, the kernel sets MSG_CTRUNC
and silently discards the overflowing ancillary data. For SCM_RIGHTS,
this means passed file descriptors are lost without any error.
Add a MSG_CTRUNC check right after the existing MSG_TRUNC check so
that dump fails explicitly instead of silently producing an incomplete
image.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
We saw compilation errors like:
error: call to ‘__open_missing_mode’ declared with attribute error:
open with O_CREAT or O_TMPFILE in second argument needs 3 arguments
Let's fix them by adding mode 0777 everywhere.
Before this change the mode was taken randomly from stack (according to
man 2 open) and that is likely not what we want.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
prepare_cgroup_namespace() can call userns_call() to move
the task into a cgroup. userns_call() uses
sendmsg() with SCM_CREDENTIALS to communicate with usernsd.
If the user namespace maps are configured such that the parent's UID
(typically 0) is not mapped to the same UID in the child namespace
(i.e., lower_first != 0), the getuid() syscall in the child will return
the overflow UID (65534) until the child's credentials are explicitly
set within the namespace.
When sendmsg() is called with SCM_CREDENTIALS containing the overflow UID,
the kernel's __scm_send function returns -EINVAL, causing the restore
to fail.
[avagin: tweaked the commit message]
Signed-off-by: Efim Verzakov <efimverzakov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In unix_collect_one(), icons (in-flight connections) are added to the
global unix_listen_icons hash table. Previously, if xzalloc() failed
mid-loop while allocating an icon, the code could leave partially
inserted icons in the global hash, resulting in dangling pointers and
potential use-after-free crashes.
This patch changes the logic to pre-allocate all unix_sk_listen_icon
nodes before inserting any of them into unix_listen_icons. If allocation
fails, the temporary list is freed and the function aborts before
mutating the global hash. This ensures that the hash is only updated
when all allocations succeed, and avoids the need to traverse and remove
icons from the hash on error.
Signed-off-by: Ahmed Elaidy <elaidya225@gmail.com>
Pavel Emelyanov, the founder and long-time leader of the CRIU project,
is moving to a retired role. As the project's inventor, Pavel's vision
and leadership over many years were fundamental in bringing CRIU to its
current status as a production-ready solution.
Andrey Vagin is appointed as the chief maintainer.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We need to support restoring processes on different nodes or subnets
where the original socket IPs may no longer be valid. This change
introduces a new plugin hook, CR_PLUGIN_HOOK__UPDATE_INETSK, and wires
it into both the plugin API and the legacy descriptor autogen so that
existing plugins remain compatible.
The hook is invoked from collect_one_inetsk() before address validation,
port reservation, or bind()/connect(). A plugin may rewrite the IPv4 or
IPv6 src/dst address fields in InetSkEntry in‑place and return 0.
Returning -ENOTSUP skips to the next plugin; any other negative value
aborts the restore for that socket. Only the IP addresses may change —
family, ports, ifname and length constraints remain enforced.
This mechanism is mainly intended for cross‑node or Kubernetes‑style
scenarios where the final IP is only known after the target network
namespace is created and configured. Pre‑editing image files would be
awkward or infeasible otherwise.
Note: for established TCP connections, external coordination or preserving
the original 4‑tuple is still required. This hook only adjusts addresses
and does not modify TCP state.
Signed-off-by: Rowan-Ye <rowenye1@gmail.com>
mnt_id was declared as uint32_t but assigned -1 when absent, which yields
UINT32_MAX. When passed to mntns_get_root_by_mnt_id(int), the conversion
from UINT32_MAX to int is implementation-defined and can become a large
positive value, potentially causing lookup_nsid_by_mnt_id() to return NULL
and trigger BUG_ON().
Change mnt_id to int with an explicit cast from f_handle->mnt_id when
present, so the sentinel -1 is preserved reliably across platforms.
Signed-off-by: 3idey <elaidya225@gmail.com>
Add checks for mntns_get_root_by_mnt_id() return value before using it
in openat() calls. This prevents using an invalid file descriptor if
the mount namespace root lookup fails.
Add error logging when mntns_get_root_by_mnt_id() fails to provide
diagnostic context about which mount namespace and path were being
accessed.
Also rename local variable 'path' to 'fpath' to avoid shadowing the
outer scope variable of the same name.
Signed-off-by: 3idey <elaidya225@gmail.com>
Before that patch we always had exactly the same magic and extentsion
patterns generated.
While on it let's fix the data restrictions:
- The length of extension and magic should be non-zero.
- Let's explicitly wrap extension characters with 256.
Fixes: #2886
Co-developed-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In ns flavor for instance the binfmt_misc is not c/r-ed, but without
this cleanup the test will not detect that as it would inherit correct
unchanged binfmt_misc step which was there on dump.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In zdtm/static/binfmt_misc we print the string which contains random
bytes, some of which may not map to utf-8. So let's ignore those bytes
we can't show in utf-8.
Else we can get:
File ".../criu/test/zdtm.py", line 660, in print_output
print(output.read())
~~~~~~~~~~~^^
File "<frozen codecs>", line 325, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 180: invalid continuation byte
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The Linux kernel already supports per user namespace sandboxed mounts:
21ca59b365c0 ("binfmt_misc: enable sandboxed mounts")
The overall dump/restore logic is based on the fact that a binfmt_misc
superblock is static and is allocated once per a binfmt_misc mount
within a given user namespace. So the code makes a temporary mount to
read/write the entries and then removes it. The binfmt_misc data is
stored to the USERNS image.
Signed-off-by: Dmitry Sepp <dmitry.sepp@virtuozzo.com>
Detect if the kernel supports binfmt_misc sandboxing and store the
result in kerndat.
The result will be used by the code that dumps and restores binfmt_misc
entries.
Signed-off-by: Dmitry Sepp <dmitry.sepp@virtuozzo.com>
Remove the OpenVZ specific code that was not used outside of the OpenVZ
infrastructure in preparation for implementing support for upstream
Linux kernel binfmt_misc sandboxing.
Signed-off-by: Dmitry Sepp <dmitry.sepp@virtuozzo.com>
Change compel_task_size() to probe the actual kernel address space
limit at runtime via mmap() with MAP_FIXED_NOREPLACE flag.
On systems where the CPU supports 5-level paging but the kernel
doesn't have it enabled, we need to detect the actual task size the
kernel is using.
On x86-64, task_size is either (1UL << 47) for 4-level paging or
(1UL << 56) for 5-level paging. The function probes by attempting
to mmap at the 4-level boundary and if it succeeds or the address
is already occupied, the kernel supports 5-level paging.
Fixes: #2877
Signed-off-by: Tushar Mohapatra <tusharmohapatra.gig@gmail.com>
Add a test that creates a SIGEV_THREAD_ID posix timer targeting the
thread leader in a multithreaded process. This exercises the code path
where encode_notify_thread_id() must look up the thread leader's vtid
in threads[0].ns[0].virt.
Without the fix in the previous commit, this test fails during dump
with:
Error (criu/timer.c:329): Unable to convert the notify thread id <pid>
The test creates a worker thread (so the process is multithreaded, which
triggers the collect_threads() path) and a SIGEV_THREAD_ID timer on the
main thread, then verifies the timer still fires after C/R.
Signed-off-by: 3idey <elaidya225@gmail.com>
In collect_threads(), threads[0] (the thread leader) gets its .real pid
set but .ns[0].virt is left uninitialized. Later in dump_one_task(),
item->pid->ns[0].virt is set from the parasite misc data, but
threads[0].ns[0].virt is not populated until dump_task_threads() runs.
The problem is that parasite_dump_posix_timers_seized() is called
*before* dump_task_threads(). When a posix timer has SIGEV_THREAD_ID
notification targeting the thread leader, encode_notify_thread_id()
looks up threads[i].ns[0].virt and finds an uninitialized (garbage)
value for threads[0]. This causes:
- On dump: the garbage vtid is written into the image as
notify_thread_id.
- On restore: timer_create() fails with -EINVAL because the
notify_thread_id is invalid.
Fix this by initializing threads[0].ns[0].virt right after
item->pid->ns[0].virt is set, before the posix timer dump.
Fixes: #2887
Signed-off-by: 3idey <elaidya225@gmail.com>
page_pipe_from_pagemap() opens a page_read via open_page_read() but
never calls pr.close() on error or success paths. This leaks the
pagemap and pages image file descriptors, and any parent page_read
chain.
Add proper cleanup using goto err pattern to ensure pr.close() is
always called before returning. Also destroy the page_pipe on
fill_page_pipe() failure to avoid leaking its memory and pipe FDs.
Signed-off-by: 3idey <elaidya225@gmail.com>
In container setups, particularly k8s, cgroup may be used to
restrict what GPUs a process has access to. CRIU may then be used
to checkpoint that process while CRIU itself has full access to
all GPUs.
In this case, the kfd CRIU ioctl will return only a subset of the
ioctls visible through sysfs.
Don't write these devices or any links connected to them to the
tology dump files.
Signed-off-by: David Francis <David.Francis@amd.com>
When irmap_queue_cache fails, the remaining fanotify mark entries
and the mark array are not freed, causing a memory leak.
Add cleanup label to ensure proper deallocation of remaining entries
and the mark array on error paths.
Signed-off-by: 3idey <elaidya225@gmail.com>
When irmap_queue_cache fails, the remaining inotify watch descriptors
and the wd array are not freed, causing a memory leak.
Add cleanup label to ensure proper deallocation of remaining entries
and the wd array on error paths.
Signed-off-by: 3idey <elaidya225@gmail.com>
Error messages now include additional context to aid debugging:
- Device and inode numbers for file handles
- Watch descriptor (wd) for inotify operations
- Mask values for fanotify marks
- Mount ID for mount-related operations
This makes it much easier to diagnose checkpoint/restore failures
by providing complete information about which watch or mark failed
and why, without needing to add debug logging.
Signed-off-by: 3idey <elaidya225@gmail.com>
When restoring inotify watches, the restore_one_inotify() function opens
a file descriptor via get_mark_path() and stores it in the 'target'
variable. However, in two error paths, the function returns directly
without properly closing this file descriptor:
1. When INOTIFY_IOC_SETNEXTWD ioctl fails (line 556)
2. When has_inotify_setnextwd is true but watch descriptor mismatch
occurs (line 577)
Both cases bypass the cleanup code at the 'err' label which calls
close_safe(&target), resulting in a file descriptor leak.
Fix this by using 'goto err' instead of 'return -1' in both error paths,
ensuring proper cleanup of the target file descriptor.
Signed-off-by: 3idey <elaidya225@gmail.com>
Add repository-specific guidance for GitHub Copilot in
.github/copilot-instructions.md. This file includes information about:
- Coding style (Linux Kernel Coding Style)
- Architectural overview of the project
- PIE code requirements (must be self-contained and depend on compel)
- Descriptions of CRIU commands
- ZDTM test suite details
- Commit message formatting guidelines
This is just initial skeleton designed to optimize GitHub Copilot
reviews.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
When `opts.pid` is explicitly set to `os.getpid()`, `pycriu` fails to
daemonize the `criu` process. This causes `criu` to run as a child of
the dumped process, leading to the error "The criu itself is within
dumped tree".
This can be fixed by modifying `_send_req_and_recv_resp` to check if the
target PID matches the current process PID. If so, it enables daemon
mode, ensuring `criu` is detached and the dump succeeds.
Signed-off-by: unichronic <ishuvam.pal@gmail.com>
In a simple case where the parent process and the child one are in one
pid namespace we can safely use vpid(item) to prace the child. But, for
the cases where the child is a pid namespace init, or the child is put
into external pid namespace, the parent and the child have different pid
namespaces and using pid vpid(item) (which e.g. for init will always be
1 here) to ptrace the child process is inorrect.
Let's use the pid reported to us from clone as it's always the right pid
of the child from the parent's point of view.
Fixes: 7dd583002 ("restore: add infrastructure to enable shadow stack")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The return value of sys_rseq was previously ignored during
unregistration, under the assumption that it would not fail if the rseq
structure was properly registered.
However, if sys_rseq fails, the kernel retains the registration. If the
memory containing the rseq structure is subsequently unmapped or reused,
kernel updates to the rseq area can cause the process to crash (e.g.,
via SIGSEGV).
Check the return value of sys_rseq. If it fails, log the error code and
abort the restoration process. This makes rseq unregistration failures
fatal and explicit, aiding in debugging and preventing later obscure
crashes.
Signed-off-by: liqiang2020 <liqiang64@huawei.com>
Fedora rawhide ships a pre-release of GCC 16 which produces following
error:
uprobes.c:34:22: error: variable ‘dummy’ set but not used [-Werror=unused-but-set-variable=]
34 | volatile int dummy = 0;
| ^~~~~
Marking this variable as "__maybe_unused" to fix the error.
Signed-off-by: Adrian Reber <areber@redhat.com>
In some cases, CRIU can observe tasks that exit during checkpointing,
and sets the state of these tasks to COMPEL_TASK_DEAD.
This patch adds a string representation of this value that can be used
by CRIT when decoding the images.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIU defines the following constants for task state in compel/include/uapi/task-state.h
COMPEL_TASK_ALIVE = 0x01
COMPEL_TASK_STOPPED = 0x03
COMPEL_TASK_ZOMBIE = 0x06
Thus, we need to swap the values for "zombie" and "stopped" used in CRIT.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When running the command 'make docker-test', almost all zdtm tests fail,
logging 'ip: not found'. 'ip' command of the iproute2 package was missing.
So added the package to the list of dependencies in 'apt-packages.sh'. Now
tests run
Signed-off-by: ImranullahKhann <imranullahkhann2004@gmail.com>
As of Alpine Linux 3.19, musl libc no longer contains separate
fopen64(), fseeko64(), or ftello64() functions. This causes building
CRIU with amdgpu plugin to fail with the following error:
amdgpu_plugin.c: In function 'parallel_restore_bo_contents':
amdgpu_plugin.c:2286:17: error: implicit declaration of function 'fseeko64'; did you mean 'fseeko'? [-Wimplicit-function-declaration]
2286 | fseeko64(bo_contents_fp, entry->read_offset + offset, SEEK_SET);
| ^~~~~~~~
| fseeko
make[2]: *** [Makefile:31: amdgpu_plugin.so] Error 1
make[1]: *** [Makefile:363: amdgpu_plugin] Error 2
To fix this, add the missing $(DEFINES) to plugin builds, and since we
always compile with _FILE_OFFSET_BITS=64, we don't need the 64 suffix.
Fixes: #2826
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The initialization of the struct timespec used as clockid input
parameter was removed in commit:
b4441d1bd8 ("restorer.c: rm unneded struct init")
This causes the build to fail on Alpine with clang version 21.1.2:
GEN criu/pie/parasite-blob.h
criu/pie/restorer.c:1230:39: error: variable 'ts' is uninitialized when passed as a const pointer argument here [-Werror,-Wuninitialized-const-pointer]
1230 | if (sys_clock_gettime(t->clockid, &ts)) {
| ^~
1 error generated.
make[2]: *** [/criu/scripts/nmk/scripts/build.mk:118: criu/pie/restorer.o] Error 1
make[1]: *** [criu/Makefile:59: pie] Error 2
make: *** [Makefile:278: criu] Error 2
To fix this, we remove the "const" from the declaration of
clock_gettime. Since the kernel writes the current time into
the struct timespec provided by the caller, the pointer must
be writable.
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
After commit [1] we accidentally stopped reporting the errors from
kerndat_has_timer_cr_ids(), let's fix that.
Fixes: 1eaa870cc ("kerndat: check that hardware breakpoints work") [1]
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The "man 2 close":"Dealing with error returns from close()" says:
"Retrying the close() after a failure return is the wrong thing to do"
We should not leave the fd there, attempting to close it again on next
close()/close_safe() may lead to accidentally closing something else.
It confirms with the kernel code where sys_close() removes fd from
fdtable in this stack:
+-> sys_close
+-> file_close_fd
+-> file_close_fd_locked
+-> rcu_assign_pointer(fdt->fd[fd], NULL)
If there was an fd this stack is always reached and fd is always
removed.
Let's replace the fd with -1 after close no matter what.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The README currently uses an external link to criu.org for the embedded
CRIU logo. Loading this URL when viewing the README on GitHub sometimes
fails with "Error Fetching Resource". Using a local copy of the logo
fixes this issue.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Docker version 28 broke container restore in combination with network
namespaces. The workaround in the CI script was excluding Docker version
28. Now that there is also Docker version 29, which is still broken,
this also excludes Docker version 29.
Signed-off-by: Adrian Reber <areber@redhat.com>
Commit "plugin: Add DUMP_DEVICES_LATE callback" introduced a new plugin
callback that is invoked in cr_dump_tasks(). The return value of this
callback was assigned to the variable ret. However, this variable is later
used as the return value when goto err is triggered in subsequent
conditions. As a result, CRIU exits with "Dumping finished successfully" even
when some actions have failed and inventory.img has not been created.
To fix this, we replace ret with exit_code and use it only when it is
actually needed.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Introduce an opt-in mode for building and running ZDTM static tests
with Guarded Control Stack (GCS) enabled on AArch64.
Changes:
- Support `GCS_ENABLE=1` builds, adding `-mbranch-protection=standard`
and `-z experimental-gcs=check` to CFLAGS/LDFLAGS.
- Export required GLIBC_TUNABLES at runtime via `TEST_ENV`.
- %.pid rules to prefix test binaries with `$(TEST_ENV)`
so the tunables are set when running tests.
- Makefile rules for selectively enabling GCS in tests
Usage:
# Build and run with GCS enabled
make -C zdtm/static GCS_ENABLE=1 posix_timers
GCS_ENABLE=1 ./zdtm.py run --keep-img=always \
-t zdtm/static/posix_timers
By default (`GCS_ENABLE` unset or 0), test builds and runs are
unchanged.
NOTE: This assumes that the test victim was compiled also using
GCS_ENABLE=1 so that the proper GCS AArch64 ELF headers are present
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Reviewed-by: Alexander Mikhalitsyn aleksandr.mikhalitsyn@canonical.com
This commit finalizes AArch64 Guarded Control Stack (GCS)
support by wiring the full dump and restore flow.
The restore path adds the following steps:
- Define shared AArch64 GCS types and constants in a dedicated header
for both compel and CRIU inclusion
- compel: add get/set NT_ARM_GCS via ptrace, enabling user-space
GCS state save and restore.
- During restore switch to the new GCS (via GCSSTR) to place capability
token sa_restorer address
- arch_shstk_trampoline() — We enable GCS in a trampoline that using
prctl(PR_SET_SHADOW_STACK_STATUS, ...) via inline SVC. The trampoline
ineeded because we can’t RET without a valid GCS.
- restorer: map the recorded GCS VMA, populate contents top-down with
GCSSTR, write the signal capability at GCSPR_EL0 and the valid token at
GCSPR_EL0-8, then switch to the rebuilt GCS (GCSSS1)
- Save and restore registers via ptrace
- Extend restorer argument structures to carry GCS state
into post-restore execution
- Add shstk_set_restorer_stack(): sets tmp_gcs to temporary restorer
shadow stack start
- Add gcs_vma_restore implementation (required for mremap of the GCS VMA)
Tested with:
GCS_ENABLE=1 ./zdtm.py run -t zdtm/static/env00
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Add debug and info messages to log Guarded Control Stack state when
dumping AArch64 threads. This includes the following values:
- gcspr_el0
- features_enabled
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
[ alex: cleanup fixes ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: Mike Rapoport <rppt@kernel.org>
- Define user_aarch64_gcs_entry in core-aarch64.proto to store
Guarded Control Stack state (gcspr_el0, features_enabled).
- Extend thread_info_aarch64 with an optional gcs field
Also extend thread_info_aarch64 with an optional gcs field
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Introduce an opt-in mode for building and running compel tests
with Guarded Control Stack (GCS) enabled on AArch64.
Changes:
- Extend compel/test/infect to support `GCS_ENABLE=1` builds,
adding `-mbranch-protection=standard` and
`-z experimental-gcs=check` to CFLAGS/LDFLAGS.
- Export required GLIBC_TUNABLES at runtime via `TEST_ENV`.
Usage:
make -C compel/test/infect GCS_ENABLE=1
make -C compel/test/infect GCS_ENABLE=1 run
By default (`GCS_ENABLE` unset or 0), builds and runs are unchanged.
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
When GCS is enabled, the kernel expects a capability token at GCSPR_EL0-8
and sa_restorer at GCSPR_EL0-16 on rt_sigreturn. The sigframe must be
consistent with the kernel’s expectations, with GCSPR_EL0 advanced by -8
having it point to the token on signal entry. On rt_sigreturn, the kernel
verifies the cap at GCSPR_EL0, invalidates it and increments GCSPR_EL0 by 8
at the end of gcs_restore_signal() .
Implement parasite_setup_gcs() to:
- read NT_ARM_GCS via ptrace(PTRACE_GETREGSET)
- write (via ptrace) the computed capability token and restorer address
- update GCSPR_EL0 to point to the token's location
Call parasite_setup_gcs() into parasite_start_daemon() so the sigreturn
frame satisfies kernel's expectation
Tests with GCS remain opt‑in:
make -C compel/test/infect GCS_ENABLE=1 && make -C compel/test/infect run
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
[ alex: cleanup fixes ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: Mike Rapoport <rppt@kernel.org>
Add basic prerequisites for Guarded Control Stack (GCS) state on AArch64.
This adds a gcs_context to the signal frame and extends user_fpregs_struct_t to
carry GCS metadata, preparing the groundwork for GCS in the parasite.
For now, the GCS fields are zeroed during compel_get_task_regs(), technically
ignoring GCS since it does not reach the control logic yet; that will be
introduced in the next commit.
The code path is gated and does not affect normal tests. Can be explicitly
enabled and tested via:
make -C infect GCS_ENABLE=1 && make -C infect run
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
[ alex: clean up fixes ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: Mike Rapoport <rppt@kernel.org>
Introduce ARM64 Guarded Control Stack (GCS) constants and macros
in a new uapi header for use in both CRIU and compel.
Includes:
- NT_ARM_GCS type
- prctl(2) constants for GCS enable/write/push modes
- Capability token helpers (GCS_CAP, GCS_SIGNAL_CAP)
- HWCAP_GCS definition
These are based on upstream Linux definitions
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: Mike Rapoport <rppt@kernel.org>
Refactor user_fpregs_struct_t to wrap user_fpsimd_state in a
dedicated struct, preparing for future extending by just
adding new members
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
[ alex: fixes ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Reviewed-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Acked-by: Mike Rapoport <rppt@kernel.org>
At least on tests running on Fedora rawhide following error could be
seen:
```
criu/tty.c: In function 'pts_fd_get_index':
criu/tty.c:262:21: error: initialization discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers]
262 | char *pos = strrchr(link->name, '/');
|
```
This fixes it.
Signed-off-by: Adrian Reber <areber@redhat.com>
Static code analysis reported:
1. criu/cr-restore.c:2438:2: var_decl: Declaring variable "end_vma"
without initializer.
4. criu/cr-restore.c:2451:5: assign: Assigning: "s_vma" = "&end_vma",
which points to uninitialized data.
7. criu/cr-restore.c:2449:4: uninit_use: Using uninitialized value
"s_vma->list.next".
This tries to fix it by initializing the variable.
Signed-off-by: Adrian Reber <areber@redhat.com>
Static code analysis reported:
criu/cr-dump.c:2328:2: identical_branches: The same code is executed
when the condition "ret" is true or false, because the code in the
if-then branch and after the if statement is identical. Should the if
statement be removed?
This is a fix for the warning.
Signed-off-by: Adrian Reber <areber@redhat.com>
The syntax of the inherit-fd functionality for unix socket and pipe
includes a colon.
Fixes: 0df3f79fc0 ("criu(8): fix --inherit-fd description")
Fixes: c37324b6d0 ("crtools: describe the inherit-fd option")
Signed-off-by: Mark Polyakov <mark@thundercompute.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
On AMD Instinct MI300 systems, restoring a large GPU application can
fail because the checkpoint size is too large and the maximum value of
an offset (with integer type) is insufficient. This problem occurs when
the total size of all buffer objects exceeds int max, not because any
single buffer is too large, but it can also happen with a large number
of small buffers.
Fixes: #2812
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
These header files are copied directly from the Linux kernel and contain
typos. We skip these files in codespell to simplify maintenance.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch updates drm.h and amdgpu_drm.h kernel headers,
and adds drm_mode.h (included by drm.h) from the rocm-7.1.0
release tag.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
amdgpu_plugin_drm.c:167:6: error: variable 'num_bos' set but not used [-Werror,-Wunused-but-set-variable]
167 | int num_bos = 0;
|
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Add a comment that explains the purpose of `retry_needed`.
Co-authored-by: Andrei Vagin <avagin@google.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Co-authored-by: Andrei Vagin <avagin@google.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Use `return 0` on success in `post_dump_dmabuf_check()` for consistency
with other functions.
Co-authored-by: Andrei Vagin <avagin@google.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
These pr_info lines begin with "CC3" and "TWI" were not meant to be
included in the patch.
Co-authored-by: Andrei Vagin <avagin@google.com>
Signed-off-by: David Francis <David.Francis@amd.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
amdgpu libraries that use dmabuf fd to share GPU memory between
processes close the dmabuf fds immediately after using them.
However, it is possible that checkpoint of a process catches one
of the dmabuf fds open. In that case, the amdgpu plugin needs
to handle it.
The checkpoint of the dmabuf fd does require the device file
it was exported from to have already been dumped
To identify which device this dmabuf fd was exprted from, attempt
to import it on each device, then record the dmabuf handle
it imports as. This handle can be used to restore it.
Signed-off-by: David Francis <David.Francis@amd.com>
The amdgpu plugin was counting how many files were checkpointed
to determine when it should close the device files.
The number of device files is not consistent; a process may
have multiple copies of the drm device files open.
Instead of doing this counting, add a new callback after all
files are checkpointed, so plugins can clean up their
resources at an appropriate time.
Signed-off-by: David Francis <David.Francis@amd.com>
Buffer objects held by the amdgpu drm driver are checkpointed with
the new BO_INFO and MAPPING_INFO ioctls/ioctl options. Handling
is in amdgpu_plugin_drm.h
Handling of imported buffer objects may require dmabuf fds to be
transferred between processes. These occur over fdstore, with the
handle-fstore id relationships kept in shread memory. There is a
new plugin callback: RESTORE_INIT to create the shared memory.
During checkpoint, track shared buffer objects, so that buffer objects
that are shared across processes can be identified.
During restore, track which buffer objects have been restored. Retry
restore of a drm file if a buffer object is imported and the
original has not been exported yet. Skip buffer objects that have
already been completed or cannot be completed in the current restore.
So drm code can use sdma_copy_bo, that function no longer requires
kfd bo structs
Update the protobuf messages with new amdgpu drm information.
Signed-off-by: David Francis <David.Francis@amd.com>
The amdgpu plugin usually calls drm ioctls through the libdrm
wrappers. However, amdgpu restore requires dealing with dmabufs
and gem handles directly, which means drm ioctls must be
called directly.
Add the drm.h header (from the kernel's uapi).
Signed-off-by: David Francis <David.Francis@amd.com>
For amdgpu plugin to call the new amdgpu drm CRIU ioctls, it needs
the amdgpu drm header file, copied from the kernel's includes.
Signed-off-by: David Francis <David.Francis@amd.com>
amdgpu dmabuf CRIU requires the ability of the amdgpu plugin
to retry.
Change files_ext.c to read a response of 1 from a plugin restore
function to mean retry.
Signed-off-by: David Francis <David.Francis@amd.com>
amdgpu represents allocated device memory as a memory mapping
of the device file. This is a non-standard VMA that must
be handled by the plugin, not the normal VMA code.
Ignore all VMAs on device files.
Signed-off-by: David Francis <David.Francis@amd.com>
This patch implements the entire logic to enable the offloading of
buffer object content restoration.
The goal of this patch is to offload the buffer object content
restoration to the main CRIU process so that this restoration can occur
in parallel with other restoration logic (mainly the restoration of
memory state in the restore blob, which is time-consuming) to speed up
the restore phase. The restoration of buffer object content usually
takes a significant amount of time for GPU applications, so
parallelizing it with other operations can reduce the overall restore
time.
It has three parts: the first replaces the restoration of buffer objects
in the target process by sending a parallel restore command to the main
CRIU process; the second implements the POST_FORKING hook in the amdgpu
plugin to enable buffer object content restoration in the main CRIU
process; the third stops the parallel thread in the RESUME_DEVICES_LATE
hook.
This optimization only focuses on the single-process situation (common
case). In other scenarios, it will turn to the original method. This is
achieved with the new `parallel_disabled` flag.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Currently the restore of buffer object comsumes a significant amount of
time. However, this part has no logical dependencies with other restore
operations. This patch introduce some structures and some helper
functions for the target process to offload this task to the main CRIU
process.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
When enabling parallel restore, the target process and the main CRIU
process need an IPC interface to communicate and transfer restore
commands. This patch adds a Unix domain TCP socket and stores this
socket in `fdstore`.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Major changes:
* plugins/amdgpu: Implement parallel restore
* Handle processes with uprobes vma
* Fix: getsockopt usage for SO_PASSCRED/SO_PASSSEC on Linux 6.16
* Relax ELF magic check to support MIPS libraries
* pagemap: prevent integer overflow in pagemap_len
This release's name is a nod to the growing challenge we face in
maintaining compatibility across the rapidly evolving Linux kernel
ecosystem.
The full changelog can be found here: https://criu.org/Download/criu/4.2.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Using sizeof(hdr) where hdr is a pointer gives the size of the pointer,
not the size of the structure it points to.
Reported-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
vsnprintf does not always return the number of bytes actually written to
the buffer.
If the output was truncated due to the buffer limit, the return value is
the total number of bytes which WOULD have been written to the final
string if enough space had been available.
This means we must cap the return value to the buffer size excluding the
terminating null byte to correctly calculate the log entry size.
Signed-off-by: Andrei Vagin <avagin@google.com>
kerndat_init() can generate a significant volume of logs. If called
before log_init(), all these messages will be saved in the
early_log_buffer, which has a limited capacity. Additionally, saving to
the early_log_buffer can introduce a performance penalty, especially
when verbose mode is not enabled.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Signed-off-by: Andrei Vagin <avagin@google.com>
When we compare two list of vma-s, we need to take into account that
some of them could be merged.
Fixes#12286
Signed-off-by: Andrei Vagin <avagin@google.com>
This functionality (#2527) is being reverted and excluded from this
release due to issue #2812.
It will be included in a subsequent release once all associated issues
are resolved.
Signed-off-by: Andrei Vagin <avagin@google.com>
This patch fixes the following error:
$ sudo make -C test/others/criu-coredump run
...
Traceback (most recent call last):
File "/home/circleci/criu/coredump/coredump", line 55, in <module>
main()
File "/home/circleci/criu/coredump/coredump", line 47, in main
coredump(opts)
File "/home/circleci/criu/coredump/coredump", line 14, in coredump
cores = generator(os.path.realpath(opts['in']))
File "/home/circleci/criu/coredump/criu_coredump/coredump.py", line 192, in __call__
self.coredumps[pid] = self._gen_coredump(pid)
File "/home/circleci/criu/coredump/criu_coredump/coredump.py", line 214, in _gen_coredump
cd.vmas = self._gen_vmas(pid)
File "/home/circleci/criu/coredump/criu_coredump/coredump.py", line 992, in _gen_vmas
v.data = self._gen_mem_chunk(pid, vma, v.filesz)
File "/home/circleci/criu/coredump/criu_coredump/coredump.py", line 879, in _gen_mem_chunk
page_mem = self._get_page(pid, page_no)
File "/home/circleci/criu/coredump/criu_coredump/coredump.py", line 797, in _get_page
num_pages = m.get("nr_pages", m.compat_nr_pages)
AttributeError: 'dict' object has no attribute 'compat_nr_pages'
+ exit 1
make[1]: *** [Makefile:3: run] Error 1
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Signed-off-by: Andrei Vagin <avagin@google.com>
Use nr_pages when available, falling back to compat_nr_pages
for compatibility.
Signed-off-by: alam0rt <sam@samlockart.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The --mntns-compat-mode option is no longer parsed with CHECK.
Use --log-file instead to test the error message.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
_init__.py defines the public API for pycriu. It is important to use
explicit imports to avoid leaking every symbol from criu.py into the
pycriu namespace. This avoids import-time side effects, prevents name
collisions, and circular-import traps.
Fixes the following lint error:
F403 `from .criu import *` used; unable to detect undefined names
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This allows users to specify RPC options when
using the check() functionality.
Co-authored-by: Andrii Herheliuk <andrii@herheliuk.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The check() functionality is very different from dump, pre-dump,
and restore. It is used only to check if the kernel supports required
features, and does not need the majority of options set via RPC.
In particular, we don't need to open `image_dir` when running `check()`
because this functionality doesn't create or process image files. In
this case, `image_dir` is used as `work_dir`, only when the latter is
not specified and a log file is used.
This patch updates the RPC options parser so that it only handles the
logging options when check() is used. Logging to a file is required when
log_file is explicitly set or no log_to_stderr is used. In such case, we
also resolve images_dir and work_dir where the log file will be created.
Fixes: #2758
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Move the logging initialization into a helper function that
can be reused.
No functional change intended.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Move the images_dir selection logic from setup_opts_from_req() into a
new function: resolve_images_dir_path(). This improves readability and
allows the code to be reused. While at it, use snprintf() instead of
sprintf() for the /proc path and ensure NULL termination after strncpy().
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Commit 9089ce8 ("service: use setproctitle") extended cr-service to
get the full path of images_dir using readlink(). However, the RPC
API was later extended to allow setting a custom path (folder) to
be set instead of passing a file descriptor, which causes readlink()
to fail as the path is not a symbolic link.
It would be better to drop the code setting the images-dir path as a
string in the proctitle.
Fixes: #2794
Suggested-by: Andrei Vagin <avagin@google.com>
Co-authored-by: Andrii Herheliuk <andrii@herheliuk.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Move the code that opens the images directory, resolves its absolute
path via readlink(), selects the work_dir, and chdir()s into it into a
new function: setup_images_and_workdir(). This reduces the size of
`setup_opts_from_req()`, improves its readability, and allows this
functionality to be reused.
While at it, change open_image_dir() to take a const char *dir
parameter, reflecting that the path is not modified by the function and
allowing callers to pass string literals without casts.
No functional changes are intended.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This change allows users to call criu.use_sk() without any
parameters to use the default socket name.
Co-authored-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Signed-off-by: Andrii Herheliuk <andrii@herheliuk.com>
[Errno 2] No such file or directory -> Socket file not found.
[Errno 111] Connection refused -> Service not running.
Signed-off-by: Andrii Herheliuk <andrii@herheliuk.com>
Use system-installed CRIU binary instead of a local file
Thanks to @avagin for suggesting this solution.
Co-authored-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Andrii Herheliuk <andrii@herheliuk.com>
Container runtimes that use libcriu (e.g., crun) need to specify a CRIU
configuration file that allows to overwrite default options set via RPC.
This is particularly useful to set options such as `--tcp-established`
via `/etc/criu/runc.conf` in Kubernetes.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Unlike "which", which is a separate executable not always installed by
default, "command -v" is a shell built-in available at least for bash,
dash, and busybox shell.
Unlike "which", "command -v" is also easier to grep for, and it is
already used in a few places here.
Inspired by commit 57251d811.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
which is used in Makefiles to check for dependencies:
Example:
export USE_ASCIIDOCTOR ?= $(shell which asciidoctor 2>/dev/null)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Don't install external pip dependencies when running `make install`.
As we are not really into developing a Python project, we should
not install additional packages. CRIU does that nowhere else.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The existing test collects all action-script hooks triggered during
`h`, `ns`, and `uns` runs with ZDTM into `actions_called.txt`, then
verifies that each hook appears at least once. However, the test does
not verify that hooks are invoked *exactly once* or in *correct order*.
This change updates the test to run ZDTM only with ns flavour as this
seems to cover all action-script hooks, and checks that all hooks are
called correctly.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch consolidates the action-script tests into
`test/others/action-script` to ensure all tests are executed
consistently and reduce duplication. Since we had two tests that appear
to do the same thing, we can remove the one that doesn't use zdtm.py.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Regardless of the actual error message, "Unknown" was always appended
to the end of the string, resulting in messages like:
"DUMP failed: Error(3): No process with such pidUnknown".
Fixed by changing standalone if statements to else-if blocks so
"Unknown" is only added when no specific error condition matches.
Signed-off-by: Andrii Herheliuk <andrii@herheliuk.com>
pycriu depends on protobuf to function correctly. Currently,
it raises an error if protobuf is not installed. Adding
protobuf to the dependencies ensures it is available after
installing pycriu.
Signed-off-by: Andrii Herheliuk <andrii@herheliuk.com>
We use LGPL-v2.1 license for the libcriu and pycriu as they are
intended to be usable by both proprietary and open-source applications.
Signed-off-by: Andrii Herheliuk <andrii@herheliuk.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
* call shstk_vma_restore() for VMA_AREA_SHSTK in vma_remap()
* delete map/copy/unmap from shstk_restore() and keep token setup + finalize
* before the loop naturally stopped at cet->ssp-8, so a -8 nudge is required here
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Co-Authored-By: Andrei Vagin <avagin@gmail.com>
[ alex: small code cleanups ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
1. create shadow stack vma during vma_remap cycle
2. copy contents from a premapped non-shstk VMA into it
3. unmap premapped non-shstk VMA
4. Mark shstk VMA for remap into the final destination
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Co-Authored-By: Andrei Vagin <avagin@gmail.com>
Co-Authored-By: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
[ alex: debugging, rework together with Andrei and code cleanup ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
* reserve space for restorer shadow stack
* set tmp_shstk at mem, advance mem by PAGE_SIZE
* forget the extra PAGE_SIZE (shstk) for premapped VMAs
Signed-off-by: Igor Svilenkov Bozic <svilenkov@gmail.com>
Co-Authored-By: Andrei Vagin <avagin@gmail.com>
[ alex: small code cleanups ]
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
* default: return whatever passed in
eg. to be used as
shtk_min_mmap_addr(kdat.mmap_min_addr)
* x86: ignore def and return 4G
On x86, CET shadow stack is required to be mapped above 4GiB
On the other hand forcing 4GiB globally would break 32-bit restores.
Co-Authored-By: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Extend the test for overwriting config options via RPC with
repeatable option (--action-script) and verify that the value
will not be silently duplicated.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When an additional configuration file is specified via RPC, this file is
parsed twice: first at an early stage to load options such as --log-file,
--work-dir, and --images-dir; and again after all RPC options and
configuration files have been evaluated.
This allows users to overwrite options specified via RPC by the
container runtime (e.g., --tcp-established). However, processing
the RPC config file twice leads to silently duplicating the values
of repeatable options such as `--action-script`.
To address this problem, we adjust the order of options parsing so
that the RPC config file is evaluated only once. This change should
not introduce any functional changes. Note that this change does
not affect the logging functionality, as early log messages are
temporarily buffered and only written to the log file once it has
been initialized (see commit 1ff2333 "Printout early log messages").
Fixes#2727
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Program flow:
- Parse the test's own executable to calculate the file offset of the uprobe
target function symbol
- Enable the uprobe at the target function
- Call the target function to trigger the uprobe, and hence the uprobes vma
creation
- C/R
- Call the target function again to check that no SIGTRAP is sent, since the
uprobe is still active
At least v1.7 of libtracefs is required because that's when
tracefs_instance_reset was introduced. The uprobes API was introduced in v1.4,
and the dynamic events API was introduced in v1.3.
Ubuntu Focal doesn't have libtracefs. Jammy has v1.2.5, and Noble has v1.7.
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
This commit teaches criu to deal with processes which have a "[uprobes]" vma.
This vma is mapped by the kernel when execution hits a uprobe location. This
is done so as to execute the uprobe'd instruciton out-of-line in the special
vma. The uprobe'd location is replaced by a software breakpoint instruction,
which is int3 on x86. When execution reaches that location, control is
transferred over to the kernel, which then executes whatever handler code
it has to, for the uprobe, and then executed the replaced instruction out-of-line
in the special vma. For more details, refer to this commit:
d4b3b6384f
Reason for adding a new option
------------------------------
A new option is added instead of making the uprobes vma handling transparent
to the user, so that when a dump is attempted on a process tree in which a
process has the uprobes vma, criu will error, asking the user to use this option.
This gives the user a chance to check what uprobes are attached to the processes
being dumped, and try to ensure that those uprobes are active on restore as well.
Again, the same reason for requiring this option on restore as well. Because
if a process is dumped with an active uprobe, and on restore if the uprobe
is not active, then if execution reaches the uprobe location, then the process
will be sent a SIGTRAP, whose default behaviour will terminate and core dump
the process. This is because the code pages are dumped with the software
breakpoint instruction replacement at the uprobe'd locations. On restore, if
execution reaches these locations and the kernel sees no associated active
uprobes, then it'll send a SIGTRAP.
So, using this option is on dump and restore is an implicit guarantee on the
user's behalf that they'll take care of the active uprobes and that any future
SIGTRAPs because of this are not on us! :)
Handling uprobes vma on dump
----------------------------
We don't need to store any information about the uprobes vma because it's
completely handled by the kernel, transparent to userspace. So, when a uprobes
vma is detected, we check if the --allow-uprobes option was specified or not.
If so, then the allow_uprobes boolean in the inventory image is set (this is
used on restore). The uprobes vma is skipped from being added to the vma list.
Handling uprobes vma on restore
-------------------------------
If allow_uprobes is set in the inventory image, then check if --allow-uprobes
is specified or not. Restoring the vma is not required.
Fixes: checkpoint-restore#1961
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Add a ZDTM test case where CRIU uses a helper process to restore
a non-empty process group with a terminated leader and a Unix
domain socket. This reproduces a corner case in which mount
namespace switching can fail during restore:
https://github.com/checkpoint-restore/criu/issues/2687
Signed-off-by: Qiao Ma <mqaio@linux.alibaba.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
These tests reveal the following build error:
In file included from compel/include/uapi/compel/asm/sigframe.h:4,
from compel/plugins/std/infect.c:14:
/usr/include/asm/sigcontext.h:28:8: error: redefinition of 'struct sigcontext'
28 | struct sigcontext {
| ^~~~~~~~~~
In file included from criu/arch/aarch64/include/asm/restorer.h:4,
from criu/arch/aarch64/crtools.c:11:
/usr/include/asm/sigcontext.h:28:8: error: redefinition of 'struct sigcontext'
28 | struct sigcontext {
| ^~~~~~~~~~
Inspired by #2766 / #2767.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Compilation on gentoo/arm64 (llvm+musl) fails with:
In file included from compel/include/uapi/compel/asm/sigframe.h:4,
from compel/plugins/std/infect.c:14:
/usr/include/asm/sigcontext.h:28:8: error: redefinition of 'struct sigcontext'
28 | struct sigcontext {
| ^~~~~~~~~~
In file included from criu/arch/aarch64/include/asm/restorer.h:4,
from criu/arch/aarch64/crtools.c:11:
/usr/include/asm/sigcontext.h:28:8: error: redefinition of 'struct sigcontext'
28 | struct sigcontext {
| ^~~~~~~~~~
This is happening because <asm/sigcontext.h> and <signal.h> are
mutually incompatible on Linux.
To fix, use <signal.h> instead of <asm/sigcontext.h> for arm64
(like all others arches do).
Fixes: #2766
Signed-off-by: Pepper Gray <hello@peppergray.xyz>
page_pipe_read() expects an 'unsigned long *', but pi->nr_pages is u64.
On 32-bit platforms (e.g., armv7), passing &pi->nr_pages directly causes
a compiler error. To fix this we introduce a temporary variable and copy
the result back to pi->nr_pages.
Fixes: #2756
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Our previous mailing list had some technical issues and we created
a new one that is hopefully more reliable.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Currently we run aarch64 tests on both Cirrus CI and GitHub runners.
However, Cirrus CI fails with "Monthly compute limit exceeded!". This
change removes the redundant tests to streamline our CI process.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Ubuntu Focal Fossa (20.04) reached its end-of-life on 31 May 2025. So, move
over to using Ubuntu Jammy (22.04) base images.
Also, focal repos do not have libtracefs, which the uprobes zdtm test needs.
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Travis CI stopped providing CI minutes for open-source projects
some time ago and we have migrated to GitHub actions.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Currently, adding a package which is required either for development or testing
requires it to be added in multiple places due to many duplicated Dockerfiles
and installation scripts. This makes it difficult to ensure that all scripts
are updated appropriately and can lead to some places being missed.
This patch consolidates the list of dependencies and adds installation
scripts for each package-manager used in our CI (apk, apt, dnf, pacman).
This change also replaces the `debian/dev-packages.lst` as this subfolder
conflicts with the Ubuntu/Debian packing scripts used for CRIU:
https://github.com/rst0git/criu-deb-packages
This patch also removes the CentOS 8 build scripts as it is EOL
and the container registry is no longer available.
Signed-off-by: Shashank Balaji <shashank.mahadasyam@sony.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit adds the document to provide high-level overviews of the
CRIU project for AI assistants like Claude and Gemini.
These documents are intended to be used as context for AI-powered
developer assistants to help them understand the project's goals,
architecture, and development process. This will allow them to provide
more accurate and helpful responses to developer questions.
The documents include:
- A brief introduction to CRIU
- A quick start guide for checkpointing and restoring a simple process
- An overview of the dump and restore process
- A description of the Compel subproject
- Information about the project's coding style, code layout, and tests
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The previous commit 4cd4a6b1ac ("zdtm: stop importing junit_xml")
removed the junit_xml library, but some variables related to it were
left in the code. This commit removes the unused `tc` variable and a
call to its `add_error_info` method.
Fixes: 4cd4a6b1ac ("zdtm: stop importing junit_xml")
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On some ARM/aarch64 systems, the VDSO ELF header sets EI_OSABI to 3 (Linux),
while CRIU expects 0 (System V). This strict check causes restore to fail
with "ELF header magic mismatch"
This patch relaxes the check to accept both values, improving compatibility
with modern toolchains and kernels (e.g. Linux 6.12+)
Fixes: #2751
Signed-off-by: dong sunchao <dongsunchao@gmail.com>
During investigations, it’s much easier to read logs when regions are
printed in the start - end format rather than `start/size`.
In addition, all page counters and memory sizes are now printed in
hexadecimal, as they are hard to read in decimal form.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Variables storing page counts were previously `unsigned int`, limiting
them to a maximum of 2^32 pages. With a 4k page size, this corresponds
to a 16TB memory mapping, which is insufficient for larger mappings.
This commit changes the type for these variables to `unsigned long` to
support larger memory mappings.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Update the nr_pages field in PagemapEntry to uint64 to prepare for
checkpointing and restoring huge memory mappings.
Backward compatibility with older pagemap images is preserved.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On restore, CRIU needs to change mount namespaces to properly restore
files and unix sockets. However, the kernel prevents this if a process
is sharing its file system information (fs) with other processes.
Fixes#2687
Signed-off-by: Andrei Vagin <avagin@google.com>
On some kernels, attr/current can be intercepted by BPF LSM, causing
errors (#2033). Using attr/apparmor/current is preferable, because it
is guaranteed to return the apparmor label. attr/current will still be
used as a fallback for older kernels.
Fixes: #2033
Signed-off-by: Filip Hejsek <filip.hejsek@gmail.com>
On MIPS platforms, shared libraries may use EI_ABIVERSION = 5 to indicate
support for .MIPS.xhash sections. The previous ELF header check in
handle_binary() strictly compared e_ident against a hardcoded value,
causing legitimate shared objects to be rejected.
This patch replaces the memcmp-based check with a structured validation
of ELF magic and class, and allows EI_ABIVERSION values beside 0.
fixes: #2745
Signed-off-by: dong sunchao <dongsunchao@gmail.com>
We are dropping support for generating JUnit XML reports in zdtm.py as we've
migrated testing infrastructure entirely to `GitHub Actions` and other
third-party test runners.
This package has been removed from some distribution repositories (e.g.,
Fedora), making it simpler to remove the dependency than to force installation
via pip.
Signed-off-by: Andrei Vagin <avagin@google.com>
This change modifies the CI script to avoid Docker version 28, which has
a known regression that breaks Checkpoint/Restore (C/R) functionality.
The issue is tracked in the moby/moby project as
https://github.com/moby/moby/issues/50750.
Signed-off-by: Andrei Vagin <avagin@google.com>
Linux 6.16+ restricts SO_PASSCRED and SO_PASSSEC to AF_UNIX, AF_NETLINK, and AF_BLUETOOTH
This patch updates CRIU to check the socket family before dumping these options
Fixes: #2705
Signed-off-by: Dong Sunchao <dongsunchao@gmail.com>
SO_PASSCRED and SO_PASSSEC are only valid for AF_UNIX and AF_NETLINK
This patch updates the test logic to use a unix socket for these options,
while preserving the original value consistency check
Fixes: #2705
Signed-off-by: Dong Sunchao <dongsunchao@gmail.com>
The `offset` argument to `mmap()` was computed with a direct cast from
pointer to `off_t`:
`(off_t)addr_hint - (off_t)map_base`
This causes a build failure when compiling since pointers and `off_t`
may differ in size on some platforms.
maps12.c: In function 'mmap_pages':
maps12.c:114:50: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
114 | filemap ? fd : -1, filemap ? ((off_t)addr_hint - (off_t)map_base) : 0);
| ^
maps12.c:114:69: error: cast from pointer to integer of different size [-Werror=pointer-to-int-cast]
114 | filemap ? fd : -1, filemap ? ((off_t)addr_hint - (off_t)map_base) : 0);
The fix in this patch is to cast both pointers to `intptr_t`,
perform the subtraction in that type, and then cast the result
back to `off_t`.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Branch protection uses PAC. It cryptographically "signs" a function's
return address before it is stored on the stack. Upon return, the address
is authenticated using a secret key. If the signature is invalid, the
program will fault.
The PIE code is used for the parasite and the restorer. In both cases, it
runs in a foreign process. The case of the restorer is even trickier
because it needs to restore the original PAC keys, which invalidates
all previously "signed" pointers within the restorer itself.
Fixes#2709
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We need at least 6.16 to test MADV_GUARD_INSTALL support, but
our current Fedora Rawhide test uses only Rawhide's user space,
while using Fedora 42 kernel. Let's start using a vanilla kernel.
Suggested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Introduce a new kind of VMA - VMA_AREA_GUARD. In fact, it is not
a real VMA as it is not represented as struct vm_area_struct in
the kernel.
We want to reuse an existing vma infrastructure in CRIU to dump
an information about MADV_GUARD_INSTALL-covered address space
ranges as VMAs. Then, on restore, we need to carefully skip
those fake VMAs everywhere we expect a normal VMAs to be processed.
And only in restorer we use these VMAs to get an information about
where to call MADV_GUARD_INSTALL.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
1. get info about MADV_GUARD_INSTALL-protected pages with
help of pagemap by looking for PME_GUARD_REGION flag if /proc/<pid>/pagemap
is used or by looking for PAGE_IS_GUARD flag if ioctl(PAGEMAP_SCAN) is used
2. skip those pages
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Make should_dump_page to return int to indicate failure, also
return useful data back through the struct page_info structure
passed as a pointer.
Also, correspondingly convert all call sites.
No functional changes intended, except fixing a bug in
should_dump_page() as it could return (-1) when pmc_fill()
fails, while caller didn't expect that before.
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
The arm64 tests are currently being executed on both actuated and GitHub
runners. This change removes the actuated runner to avoid redundancy and
streamline our CI process.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The tar command was failing with the following message:
$ tar cf criu.tar ../../../criu
tar: Removing leading `../../../' from member names
tar: ../../../criu/scripts/ci/criu.tar: archive cannot contain itself; not dumped
In addition, the /vagrant no-longer exist in the new Fedora images.
bash: line 1: cd: /vagrant: No such file or directory
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Installing this package currently fails with the following message:
Package qemu is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or
is only available from another source
E: Package 'qemu' has no installation candidate
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
See the previous commit for rationale and architecture-specific details.
[ avagin: tweak code comment ]
Signed-off-by: Ignacio Moreno Gonzalez <Ignacio.MorenoGonzalez@kuka.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
After the CRIU process saves the parasite code for the target thread in
the shared mmap, it is necessary to call __clear_cache before the target
thread executes the code.
Without this step, the target thread may not see the correct code to
execute, which can result in a SIGILL signal.
For the specific arm64 case. this is important so that the newly copied
code is flushed from d-cache to RAM, so that the target thread sees the
new code.
The change is based on commit 6be10a2 by @fu.lin and on input received
from @adrianreber.
[ avagin: tweak code comment ]
Signed-off-by: Ignacio Moreno Gonzalez <Ignacio.MorenoGonzalez@kuka.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In general, we use "$(E)" instead of "$(Q) echo", but we also have
a msg-gen macro which can be used here.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Commit 68f92b551 removed images/google/protobuf directory, so it is
re-created each time during the build process.
This resulted in a weird behavior change. Previously, one could do
something like this:
git clone $CRURL criu
(cd criu && sudo make install-criu)
rm -rf criu
This worked fine, including running rm -rf as a non-root user, since no
new directories were created under criu -- all directories were still
owned by the original user.
Since commit 68f92b551 the same sequence fails:
rm: cannot remove '/home/runner/criu/images/google/protobuf/descriptor.pb-c.c': Permission denied
rm: cannot remove '/home/runner/criu/images/google/protobuf/descriptor.pb-c.d': Permission denied
rm: cannot remove '/home/runner/criu/images/google/protobuf/descriptor.pb-c.h': Permission denied
A workaround is to keep empty images/google/protobuf directory,
which is what this commit does.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Commit 68f92b551 used `$$(Q)` instead of `$(Q)` in the Makefile target,
which resulted in the following error:
$(Q) echo "Generating descriptor.pb-c.c"
/bin/sh: 1: Q: not found
Generating descriptor.pb-c.c
$(Q) protoc --proto_path=/usr/include --proto_path=images/ --c_out=images/ /usr/include/google/protobuf/descriptor.proto
/bin/sh: 1: Q: not found
as well as:
$(Q) rm -rf images/google
/bin/sh: line 1: Q: command not found
Fix it.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Currently the build scripts create the following symlink:
criu-4.1/images/google/protobuf/descriptor.proto -> /usr/include/google/protobuf/descriptor.proto
This symlink points to a system-wide absolute-path target. Also,
this symlink ends up in the release tarball. The tarball may later be
downloaded and unpacked by e.g. OS distributions. If unpacking is
done using Python 3.14+, it will fail.
This happens because Python 3.14 will switch the default behavior of
extractall() from "fully trusting the content of archive" to
"disallow common attack vectors while extracting the archive".
With this new behavior, extractall() raises an exception when at
least one file in the archive extracts or points to outside of the
extraction directory (these are called path traversal attacks and
zip slip attacks).
Reported-by: Dmitrii Kuvaiskii <dimakuv@amazon.de>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The test creates a file bindmount in criu mntns and binds it into test
mntns, this external file bindmount is autodetected and restored via
"--external mnt[]" criu option.
Note: In previous patch we fix the problem on this code path where file
bindmount restore fails as there is excess "/" in source path.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
E.g. I have a /etc/hosts in workspace mounted from the host, and get the following message.
(00.141008) 1: mnt-v2: Create plain mountpoint /tmp/.criu.mntns.K1biY1/mnt-0000000938 for 938
(00.141546) 1: mnt-v2: Mounting unsupported @938 (0)
(00.141887) 1: mnt-v2: Bind /tmp/agent/1-d8c746c6fda3a8b2/workspace/etc/hosts/ to /tmp/.criu.mntns.K1biY1/mnt-0000000938
(00.142179) 1: Error (criu/mount-v2.c:319): mnt-v2: Failed to open_tree /tmp/agent/1-d8c746c6fda3a8b2/workspace/etc/hosts/: Not a directory
(00.143774) Error (criu/cr-restore.c:2320): Restoring FAILED.
Signed-off-by: Chuan Qiu <qiuc12@gmail.com>
Add ZDTM static tests for IP4/ICMP and IP6/ICMP
socket feature.
Signed-off-by: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
Currently there is no option to checkpoint/restore programs that use
ICMP sockets, such as `ping`. This patch adds support for the same.
Fixes#2557
Signed-off-by: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
net/unix/max_dgram_qlen can't be tuned from non-root userns before:
v5.17-rc1~170^2~215 ("net: Enable max_dgram_qlen unix sysctl to be
configurable by non-init user namespaces")
Signed-off-by: Andrei Vagin <avagin@google.com>
We dump sysctls from criu user namespace, but restore from restored user
namespace. So group id values should be mapped to the restored user
namespace gid space to restore correctly.
Signed-off-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We have ability to skip sysctl if there is no value, but we still give
n requests to sysctl_op, that is not correct and probably can segfault
on nullptr access. Fix it by adding ri to count non skipped requests.
To be on the safe side, let's add a check that ri == n on read, as we
should not do any skips there.
While on it lets fix bad error message prefix: s/unix/ipv4/.
Remove excess has_iarg set, and add sarg reset to NULL for the case
sysctl_op skipped it.
Signed-off-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Having CTL_FLAGS_IPC_EACCES_SKIP == (CTL_FLAGS_OPTIONAL |
CTL_FLAGS_READ_EIO_SKIP) is probably not what we want. So let's make it
a real distinct flag.
Fixes: 840735aa0 ("ipc_sysctl: Prioritize restoring IPC variables using non usernsd approach")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The `criu cpuinfo check` command calls cpu_validate_cpuinfo(), which
attempts to open the cpuinfo.img file using `open_image()`. If the
image file is not found, `open_image()` returns an "empty image"
object. As a result, `cpu_validate_cpuinfo()` tries to read from it
and fails with the following error:
(00.002473) Error (criu/protobuf.c:72): Unexpected EOF on (empty-image)
This patch adds a check for an empty image and appropriate error message.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The cpuinfo command requires a "dump" or "check" subcommand. Thus, we
replace `CR_CPUINFO` with `CR_CPUINFO_DUMP` and `CR_CPUINFO_CHECK`.
This allows us to remove unnecessary subcommand check in
`image_dir_mode()` and perform all parsing in `parse_criu_mode()`.
With this change the check for validating the cpuinfo subcommand is
now done only once with `CR_CPUINFO_DUMP` or `CR_CPUINFO_CHECK` enum.
Signed-off-by: Liana Koleva <43767763+lianakoleva@users.noreply.github.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIU currently requires a number of dependencies in order to build from
source. The package names vary across distributions and package
managers. A Nix flake allows developers to spin up a dev environment
with `nix develop`, eliminating the hassle of manual dependency
management. It also prevents polluting the global package set on the
machine.
Signed-off-by: Prajwal S N <prajwalnadig21@gmail.com>
In this test we want to ensure that contents of droppable mappings
and mappings with MADV_WIPEONFORK is properly restored in
parent/child processes.
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Support MAP_DROPPABLE [1] by detecting it from /proc/<pid>/smaps
and restoring it as a normal private mapping flag on vma with only
difference that instead of MAP_PRIVATE we should use MAP_DROPPABLE.
[1] 9651fcedf7
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
Support VM_WIPEONFORK [1] by detecting it from /proc/<pid>/smaps
and setting a corresponding MADV_WIPEONFORK flag on vma.
[1] d2cd9ede6e
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
The opts['action'] contains actor function and not the action name, so
we should compare it with a function.
While on it let's also add a comment about --criu-bin option if CRIU
binary is missing.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
By default zdtm expects that criu is built from source first and only
then you can run zdtm tests against it. But what if you really want to
run tests against a criu version installed on the system? Yes there is
already a nice option for zdtm to change the criu binary it uses
"--criu-bin", but it would still end up using the pycriu module from
source and you would still have to build everything beforehand.
Let's add an option to change the path where zdtm searches for pycriu
module "--pycriu-search-path". This way we can run zdtm tests on the
criu installed on the system directly without building criu from source,
e.g. on Fedora it works like:
test/zdtm.py run --criu-bin /usr/sbin/criu \
--pycriu-search-path /usr/lib/python3.13/site-packages \
-t zdtm/static/env00
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This patch implements the entire logic to enable the offloading of
buffer object content restoration.
The goal of this patch is to offload the buffer object content
restoration to the main CRIU process so that this restoration can occur
in parallel with other restoration logic (mainly the restoration of
memory state in the restore blob, which is time-consuming) to speed up
the restore phase. The restoration of buffer object content usually
takes a significant amount of time for GPU applications, so
parallelizing it with other operations can reduce the overall restore
time.
It has three parts: the first replaces the restoration of buffer objects
in the target process by sending a parallel restore command to the main
CRIU process; the second implements the POST_FORKING hook in the amdgpu
plugin to enable buffer object content restoration in the main CRIU
process; the third stops the parallel thread in the RESUME_DEVICES_LATE
hook.
This optimization only focuses on the single-process situation (common
case). In other scenarios, it will turn to the original method. This is
achieved with the new `parallel_disabled` flag.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Currently the restore of buffer object comsumes a significant amount of
time. However, this part has no logical dependencies with other restore
operations. This patch introduce some structures and some helper
functions for the target process to offload this task to the main CRIU
process.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
When enabling parallel restore, the target process and the main CRIU
process need an IPC interface to communicate and transfer restore
commands. This patch adds a Unix domain TCP socket and stores this
socket in `fdstore`.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Currently, parallel restore only focuses on the single-process
situation. Therefore, it needs an interface to know if there is only one
process to restore. This patch adds a `has_children` function in
`pstree.h` and replaces some existing implementations with this
function.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Currently, when CRIU calls `cr_plugin_init`, `fdstore` is not
initialized. However, during the plugin restore procedure, there may be
some common file operations used in multiple hooks. This patch moves
`cr_plugin_init` after `fdstore_init`, allowing `cr_plugin_init` to use
`fdstore` to place these file operations.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Currently, in the target process, device-related restore operations and
other restore operations almost run sequentially. When the target
process executes the corresponding CRIU hook functions, it can't perform
other restore operations. However, for GPU applications, some device
restore operations have no logical dependencies on other common restore
operations and can be parallelized with other operations to speed up the
process.
Instead of launching a thread in child processes for parallelization,
this patch chooses to add a new hook, `POST_FORKING`, in the main CRIU
process to handle these restore operations. This is because the
restoration of memory state in the restore blob is one of the most
time-consuming parts of all restore logic. The main CRIU process can
easily parallelize these operations, whereas parallelizing in threads
within child processes is challenging.
- POST_FORKING
*POST_FORKING: Hook to enable the main CRIU process to perform some
restore operations of plugins.
Signed-off-by: Yanning Yang <yangyanning@sjtu.edu.cn>
Building CRIU on Ubuntu 20.04 fails with the following error:
criu/sk-inet.c: In function 'can_dump_ipproto':
criu/sk-inet.c:131:16: error: 'IPPROTO_MPTCP' undeclared (first use in this function); did you mean 'IPPROTO_MTP'?
131 | if (proto == IPPROTO_MPTCP)
| ^~~~~~~~~~~~~
| IPPROTO_MTP
Add definition for MPTCP to fix this error.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The container checkpointing procedure in Kubernetes freezes running
containers to create a consistent snapshot of both the runtime state
and the rootfs of the container. However, when checkpointing a GPU
container, the container must be unfrozen before invoking the
cuda-checkpoint tool.
This is achieved in prepare_freezer_for_interrupt_only_mode(), which
needs to be called before the PAUSE_DEVICES hook. The patch introducing
this functionality fixes this problem for containers with multiple
processes. However, if the container has a single process,
prepare_freezer_for_interrupt_only_mode() must be invoked immediately
before the PAUSE_DEVICES hook.
Fixes: #2514
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
In 0a7c5fd1bd we swapped the BSD
implementation of strlcat and strlcpy in favor of our own replacement.
The checks and the predefined macros are not needed anymore.
Signed-off-by: Lorenzo Fontana <fontanalorenz@gmail.com>
In some cases, they might not work in virtual machines if the hypervisor
doesn't virtualize them. For example, they don't work in AMD SEV virtual
machines if the Debug Virtualization extension isn't supported or isn't
enabled in SEV_FEATURES.
Fixes#2658
Signed-off-by: Andrei Vagin <avagin@gmail.com>
With Go version 1.24, ListenConfig now uses MPTCP by default [1].
Checkpoint/restore for this protocol is not currently supported
and adding support requires kernel changes that are not trivial
to implement. As a result, checkpointing of many containers that
run Go programs is likely to fail with the following error [2]:
(00.026522) Error (criu/sk-inet.c:130): inet: Unsupported proto 262 for socket 2f9bc5
This patch adds a message with suggested workaround for this problem.
[1] https://go.dev/doc/go1.24#netpkgnet
[2] https://github.com/checkpoint-restore/criu/issues/2655
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
It makes root mount readonly and checks that it is still readonly after
migration.
Make zdtm/static writable for logs via "bind" desc option.
v2: explain why we don't have explicit rw/ro flag check
v3: use new zdtm "bind" desc option
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Add {'bind': 'path/to/bindmount'} zdtm descriptor option, so that in
test mount namespace a directory bindmount can be created before running
the test.
This is useful to leave test directory writable (e.g. for logs) while
the test makes root mount readonly. note: We create this bindmount early
so that all test files are opened on it initially and not on the below
mount. Will be used in mnt_ro_root test.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Mount flags belong to mount and mount namespace of the Container, so we
should preserve them, as Container user will not expect mounts switching
between ro and rw over c/r.
Fixes: #2632
v5: fix both mount-v1 and mount-v2
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Building CRIU package on Debian 11 aarch64 fails with
criu/arch/aarch64/crtools.c: In function 'save_pac_keys':
criu/arch/aarch64/crtools.c:32:31: error: storage size of 'paca' isn't known
struct user_pac_address_keys paca;
^~~~
criu/arch/aarch64/crtools.c:33:31: error: storage size of 'pacg' isn't known
struct user_pac_generic_keys pacg;
^~~~
criu/arch/aarch64/crtools.c:47:15: error: 'HWCAP_PACA' undeclared (first use in this function); did you mean 'HWCAP_FCMA'?
if (hwcaps & HWCAP_PACA) {
^~~~~~~~~~
HWCAP_FCMA
criu/arch/aarch64/crtools.c:47:15: note: each undeclared identifier is reported only once for each function it appears in
criu/arch/aarch64/crtools.c:53:44: error: 'NT_ARM_PACA_KEYS' undeclared (first use in this function); did you mean 'NT_ARM_SVE'?
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PACA_KEYS, &iov))) {
^~~~~~~~~~~~~~~~
NT_ARM_SVE
criu/arch/aarch64/crtools.c:73:39: error: 'NT_ARM_PAC_ENABLED_KEYS' undeclared (first use in this function)
ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PAC_ENABLED_KEYS, &iov);
^~~~~~~~~~~~~~~~~~~~~~~
criu/arch/aarch64/crtools.c:82:15: error: 'HWCAP_PACG' undeclared (first use in this function); did you mean 'HWCAP_AES'?
if (hwcaps & HWCAP_PACG) {
^~~~~~~~~~
HWCAP_AES
criu/arch/aarch64/crtools.c:88:44: error: 'NT_ARM_PACG_KEYS' undeclared (first use in this function); did you mean 'NT_ARM_SVE'?
if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PACG_KEYS, &iov))) {
^~~~~~~~~~~~~~~~
NT_ARM_SVE
criu/arch/aarch64/crtools.c:33:31: error: unused variable 'pacg' [-Werror=unused-variable]
struct user_pac_generic_keys pacg;
^~~~
criu/arch/aarch64/crtools.c:32:31: error: unused variable 'paca' [-Werror=unused-variable]
struct user_pac_address_keys paca;
^~~~
criu/arch/aarch64/crtools.c: In function 'arch_ptrace_restore':
criu/arch/aarch64/crtools.c:227:31: error: storage size of 'upaca' isn't known
struct user_pac_address_keys upaca;
^~~~~
criu/arch/aarch64/crtools.c:228:31: error: storage size of 'upacg' isn't known
struct user_pac_generic_keys upacg;
^~~~~
criu/arch/aarch64/crtools.c:241:18: error: 'HWCAP_PACA' undeclared (first use in this function); did you mean 'HWCAP_FCMA'?
if (!(hwcaps & HWCAP_PACA)) {
^~~~~~~~~~
HWCAP_FCMA
criu/arch/aarch64/crtools.c:255:44: error: 'NT_ARM_PACA_KEYS' undeclared (first use in this function); did you mean 'NT_ARM_SVE'?
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PACA_KEYS, &iov))) {
^~~~~~~~~~~~~~~~
NT_ARM_SVE
criu/arch/aarch64/crtools.c:261:44: error: 'NT_ARM_PAC_ENABLED_KEYS' undeclared (first use in this function)
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PAC_ENABLED_KEYS, &iov))) {
^~~~~~~~~~~~~~~~~~~~~~~
criu/arch/aarch64/crtools.c:268:18: error: 'HWCAP_PACG' undeclared (first use in this function); did you mean 'HWCAP_AES'?
if (!(hwcaps & HWCAP_PACG)) {
^~~~~~~~~~
HWCAP_AES
criu/arch/aarch64/crtools.c:275:44: error: 'NT_ARM_PACG_KEYS' undeclared (first use in this function); did you mean 'NT_ARM_SVE'?
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PACG_KEYS, &iov))) {
^~~~~~~~~~~~~~~~
NT_ARM_SVE
criu/arch/aarch64/crtools.c:233:6: error: variable 'ret' set but not used [-Werror=unused-but-set-variable]
int ret;
^~~
criu/arch/aarch64/crtools.c:228:31: error: unused variable 'upacg' [-Werror=unused-variable]
struct user_pac_generic_keys upacg;
^~~~~
criu/arch/aarch64/crtools.c:227:31: error: unused variable 'upaca' [-Werror=unused-variable]
struct user_pac_address_keys upaca;
^~~~~
This patch adds the missing constants and structs if undefined.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIU locks the network during restore in an "empty" network namespace.
However, "empty" in this context means CRIU isn't restoring the
namespace. This network namespace can be the same namespace where
processes have been dumped and so the network is already locked in it.
Fixes#2650
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Currently we save FP regs before parasite code runs, and restore after
for --leave-running, --check-only, and in case of errors. In case of
errors the error may have happened before FP regs were saved, so we
should only restore them if they were actually saved.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
On a RHEL 8 based system building CRIU fails with:
criu/arch/aarch64/crtools.c: In function 'save_pac_keys':
criu/arch/aarch64/crtools.c:73:39: error: 'NT_ARM_PAC_ENABLED_KEYS' undeclared (first use in this function); did you mean 'NT_ARM_PACA_KEYS'?
ret = ptrace(PTRACE_GETREGSET, pid, NT_ARM_PAC_ENABLED_KEYS, &iov);
^~~~~~~~~~~~~~~~~~~~~~~
NT_ARM_PACA_KEYS
criu/arch/aarch64/crtools.c:73:39: note: each undeclared identifier is reported only once for each function it appears in
criu/arch/aarch64/crtools.c: In function 'arch_ptrace_restore':
criu/arch/aarch64/crtools.c:261:44: error: 'NT_ARM_PAC_ENABLED_KEYS' undeclared (first use in this function); did you mean 'NT_ARM_PACA_KEYS'?
if ((ret = ptrace(PTRACE_SETREGSET, pid, NT_ARM_PAC_ENABLED_KEYS, &iov))) {
^~~~~~~~~~~~~~~~~~~~~~~
NT_ARM_PACA_KEYS
This adds the missing define if it is undefined.
Signed-off-by: Adrian Reber <areber@redhat.com>
The `goto interrupt` label is unnecessary as the code directly
returns after `cuda_process_checkpoint_action()`.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When handing errors for functions such as `ptrace()`, `pipe()`, and
`fork()` it would be better to use `pr_perror` instead of `pr_err`
as it would include a message describing the encountered error.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Thomas Gleixner introduced the new interface to create posix timers
with specifed timer IDs:
ec2d0c0462
Previously, CRIU recreated timers by repeatedly creating and deleting
them until the desired ID was reached. This approach isn't fast,
especially for timers with large IDs. For example, restoring two timers
with IDs 1000000 and 2000000 took approximately 1.5 seconds.
The new `prctl()` based interface allows direct creation of timers with
specified IDs, reducing the restoration time to around 3 microseconds
for the same example.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The stack test incorrectly assumed the page immediately
following the stack pointer could never be changed. This doesn't work,
because this page can be a part of another mapping.
This commit introduces a dedicated "stack redzone," a small guard region
directly after the stack. The stack test is modified to specifically
check for corruption within this redzone.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This is highly confusing, and it seems that the ret variable
is not handled in the subsequent process.
Signed-off-by: Yuanhong Peng <yummypeng@linux.alibaba.com>
This release of CRIU (4.1.1) addresses a critical compatibility issue
introduced in the Linux kernel and back-ported to all stable releases.
The kernel commit (12f147ddd6de "do_change_type(): refuse to operate on
unmounted/not ours mounts") addressed the security issue introduced
almost 20 years ago. Unfortunately, this change inadvertently broke the
restore functionality of mount namespaces within CRIU. Users attempting
to restore a container on updated kernels would encounter the error:
"mnt-v2: Failed to make mount 476 slave: Invalid argument."
This release contains the necessary adjustments to CRIU, allowing it to
work seamlessly with kernels incorporating this security change.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
A kernel change (commit 12f147ddd6de, "do_change_type(): refuse to
operate on unmounted/not ours mounts") modified how mount propagation
properties can be changed. Previously, these properties could be changed
from any mount namespace. Now, they can only be modified from the
specific mount namespace where the target mount is actually mounted
This commit addresses this new restriction by ensuring that CRIU enters the
correct mount namespace before attempting to restore mount propagation
properties (MS_SLAVE or MS_SHARED) for a mount.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Major changes:
* RISC-V Support
* PIDFD Support
* CUDA Enhancements
* Fixes here and there
The full changelog can be found here: https://criu.org/Download/criu/4.1.
Signed-off-by: Andrei Vagin <avagin@google.com>
When using pr_err in signal handler, locking is used
in an unsafe manner. If another signal happens while holding the
lock, deadlock can happen.
To fix this, we can introduce mutex_trylock similar to
pthread_mutex_trylock that returns immediately. Due to the fact
that lock is used only for writing first_err, this change garantees
that deadlock cannot happen.
Fixes: #358
Signed-off-by: Ivan Pravdin <ipravdin.official@gmail.com>
free_userns_maps is called to clean up uid/gid map when the dump
finishes. If we try to clean up these maps in error cases, it can lead
to double free panic. So just skip cleaning up these maps and let
free_userns_maps do its job.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
There are a couple of tests that require the iptables binary.
Instead of adding a checkskip script, which could also handle this,
this change now uses CRIU's feature detection to see if the CRIU
feature 'has_ipt_legacy' exists.
Signed-off-by: Adrian Reber <areber@redhat.com>
If the tests in others/rpc are failing no information about that error
can be seen in a CI run. This change displays the log files if the test
fails.
Signed-off-by: Adrian Reber <areber@redhat.com>
The tests in others/rpc are running as non-root and
fail silently if the nftables network locking backend is used.
This switches those tests to skip the network locking.
Signed-off-by: Adrian Reber <areber@redhat.com>
The building section also contains the information how to change the
network locking backend without source code changes.
Signed-off-by: Adrian Reber <areber@redhat.com>
As different Linux distributions are switching away from iptables
to nftables, this makes it easier to compile CRIU with a different
default network locking backend. Instead of changing the source
code it is now possible to select the nft backend like this:
make NETWORK_LOCK_DEFAULT=NETWORK_LOCK_NFTABLES
Signed-off-by: Adrian Reber <areber@redhat.com>
Let's change the data types of `nbucket` and `nchain` to uint32.
This should fix the following compile-time error on arm32:
/criu/criu/pie/util-vdso.c:336: undefined reference to `__aeabi_uldivmod'
Signed-off-by: Andrei Vagin <avagin@google.com>
PAC stands for Pointer Authentication Code. Each process has 5 PAC keys
and a mask of enabled keys. All this properties have to be C/R-ed.
As they are per-process protperties, we can save/restore them just for
one thread.
Signed-off-by: Andrei Vagin <avagin@google.com>
Threads are put into cgroups through the cgroupd thread, which
communicates with other threads using a socketpair.
Previously, each thread received a dup'd copy of the socket, and did
the following
sendmsg(socket_dup_fd, my_cgroup_set);
// wait for ack.
while (1) {
recvmsg(socket_dup_fd, &h, MSG_PEEK);
if (h.pid != my_pid) continue;
recvmsg(socket_dup_fd, &h, 0);
}
close(socket_dup_fd);
When restoring many threads, many threads would be spinning in the
above loop waiting for their PID to appear.
In my test-case, restoring a process with a 11.5G heap and 491 threads
could take anywhere between 10 seconds and 60 seconds to complete.
To avoid the spinning, we drop the loop and MSG_PEEK, and add a lock
around the above code. This does not decrease parallelism, as the
cgroupd daemon uses a single thread anyway.
With the lock in place, the same restore consistently takes around 10
seconds on my machine (Thinkpad P14s, AMD Ryzen 8840HS).
There is a similar "daemon" thread for user namespaces. That already
is protected with a similar userns_sync_lock in __userns_call().
Fixes#2614
Signed-off-by: Han-Wen Nienhuys <hanwen@engflow.com>
* Hash buckets is an array of 32-bit words. While DT_HASH is 32-bit on
most platforms except s390 (where it's 64-bit).
* The bloom filter word size differs between 32-bit and 64-bit ELF
files. This commit adjusts the code to handle both cases.
Signed-off-by: Andrei Vagin <avagin@google.com>
Currently CRIU has the possibility to specify a LSM label during
restore. Unfortunately the information is completely ignored in the case
of SELinux.
This change selects the lsm label from the user if it is provided and
else the label from the checkpoint image is used.
Signed-off-by: Adrian Reber <areber@redhat.com>
With Python 3.13, the `subprocess` module now uses the
`posix_spawn()` function [1], which requires the `signal`
module to be imported.
Fixes: #2607
[1] https://docs.python.org/3/whatsnew/3.13.html#subprocess
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Add relevant elf header constants and notes for the arm platform
to enable coredump generation.
Signed-off-by: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
Add relevant elf header constants and notes for the aarch64 platform
to enable coredump generation.
Signed-off-by: समीर सिंह Sameer Singh <lumarzeli30@gmail.com>
strstartswith() function is incorrect choice for finding parent
directory so i change it to issubpath() function
Signed-off-by: Dmitrii Chervov <dschervov1@yandex.ru>
Currently Fedora rawhide based CI runs fail with:
/bin/sh: line 1: awk: command not found
Let's install it.
Signed-off-by: Adrian Reber <areber@redhat.com>
This way,
- Makefile is less cluttered;
- one can run codespell from the command line.
Fixes: fd7e97fcf ("lint: exclude tags file from codespell")
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Trying to run latest CRIU on CentOS Stream 10 or Ubuntu 24.04 (aarch64)
fails like this:
# criu/criu check -v4
[...]
(00.096460) vdso: Parsing at ffffb2e2a000 ffffb2e2c000
(00.096539) vdso: PT_LOAD p_vaddr: 0
(00.096567) vdso: DT_STRTAB: 1d0
(00.096592) vdso: DT_SYMTAB: 128
(00.096616) vdso: DT_STRSZ: 8a
(00.096640) vdso: DT_SYMENT: 18
(00.096663) Error (criu/pie-util-vdso.c:193): vdso: Not all dynamic entries are present
(00.096688) Error (criu/vdso.c:627): vdso: Failed to fill self vdso symtable
(00.096713) Error (criu/kerndat.c:1906): kerndat_vdso_fill_symtable failed when initializing kerndat.
(00.096812) Found mmap_min_addr 0x10000
(00.096881) files stat: fs/nr_open 1073741816
(00.096908) Error (criu/crtools.c:267): Could not initialize kernel features detection.
This seems to be related to the kernel (6.12.0-41.el10.aarch64). The
Ubuntu user-space is running in a container on the same kernel.
Looking at the kernel this seems to be related to:
commit 48f6430505c0b0498ee9020ce3cf9558b1caaaeb
Author: Fangrui Song <i@maskray.me>
Date: Thu Jul 18 10:34:23 2024 -0700
arm64/vdso: Remove --hash-style=sysv
glibc added support for .gnu.hash in 2006 and .hash has been obsoleted
for more than one decade in many Linux distributions. Using
--hash-style=sysv might imply unaddressed issues and confuse readers.
Just drop the option and rely on the linker default, which is likely
"both", or "gnu" when the distribution really wants to eliminate sysv
hash overhead.
Similar to commit 6b7e26547fad ("x86/vdso: Emit a GNU hash").
The commit basically does:
-ldflags-y := -shared -soname=linux-vdso.so.1 --hash-style=sysv \
+ldflags-y := -shared -soname=linux-vdso.so.1 \
Which results in only a GNU hash being added to the ELF header. This
change has been merged with 6.11.
Looking at the referenced x86 commit:
commit 6b7e26547fad7ace3dcb27a5babd2317fb9d1e12
Author: Andy Lutomirski <luto@amacapital.net>
Date: Thu Aug 6 14:45:45 2015 -0700
x86/vdso: Emit a GNU hash
Some dynamic loaders may be slightly faster if a GNU hash is
available. Strangely, this seems to have no effect at all on
the vdso size.
This is unlikely to have any measurable effect on the time it
takes to resolve vdso symbols (since there are so few of them).
In some contexts, it can be a win for a different reason: if
every DSO has a GNU hash section, then libc can avoid
calculating SysV hashes at all. Both musl and glibc appear to
have this optimization.
It's plausible that this breaks some ancient glibc version. If
so, then, depending on what glibc versions break, we could
either require COMPAT_VDSO for them or consider reverting.
Which is also a really simple change:
-VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=sysv) \
+VDSO_LDFLAGS = -fPIC -shared $(call cc-ldoption, -Wl$(comma)--hash-style=both) \
The big difference here is that for x86 both hash sections are
generated. For aarch64 only the newer GNU hash is generated. That is why
we only see this error on kernel >= 6.11 and aarch64.
Changing from DT_HASH to DT_GNU_HASH seems to work on aarch64. The test
suite runs without any errors.
Unfortunately I am not aware of all implication of this change and if a
successful test suite run means that it still works.
Looking at the kernel I see following hash styles for the VDSO:
aarch64: not specified (only GNU hash style)
arm: --hash-style=sysv
loongarch: --hash-style=sysv
mips: --hash-style=sysv
powerpc: --hash-style=both
riscv: --hash-style=both
s390: --hash-style=both
x86: --hash-style=both
Only aarch64 on kernels >= 6.11 is a problem right now, because all
other platforms provide the old style hashing.
Signed-off-by: Adrian Reber <areber@redhat.com>
Co-developed-by: Dmitry Safonov <dima@arista.com>
Co-authored-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
It is per net namespace, we need it to allow creation of unprivileged
ICMP sockets.
Note: in case this sysctl was disabled after unprivileged ICMP
socket was created we still need to somehow handle it on restore.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
For two cases libcriu was setting the RPC protobuf field `has_*` before
checking if the given parameter is valid. This can lead to situations,
if the caller doesn't check the return value, that we pass as RPC struct
to CRIU which has the `has_*` protobuf field set to true, but does not
have a verified value (or non at all) set for the actual RPC entry.
Signed-off-by: Adrian Reber <areber@redhat.com>
Temporarily disable CUDA plugin for `criu pre-dump`.
pre-dump currently fails with the following error:
Handling VMA with the following smaps entry: 1822c000-18da5000 rw-p 00000000 00:00 0 [heap]
Handling VMA with the following smaps entry: 200000000-200200000 ---p 00000000 00:00 0
Handling VMA with the following smaps entry: 200200000-200400000 rw-s 00000000 00:06 895 /dev/nvidia0
Error (criu/proc_parse.c:116): handle_device_vma plugin failed: No such file or directory
Error (criu/proc_parse.c:632): Can't handle non-regular mapping on 705693's map 200200000
Error (criu/cr-dump.c:1486): Collect mappings (pid: 705693) failed with -1
We plan to enable support for pre-dump by skipping nvidia mappings
in a separate patch.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Move `run_plugins(CHECKPOINT_DEVICES)` out of `collect_pstree()` to
ensure that the function's sole responsibility is to use the cgroup
freezer for the process tree. This allows us to avoid a time-out
error when checkpointing applications with large GPU state.
v2: This patch calls `checkpoint_devices()` only for `criu dump`.
Support for GPU checkpointing with `pre-dump` will be introduced in
a separate patch.
Suggested-by: Andrei Vagin <avagin@google.com>
Suggested-by: Jesus Ramos <jeramos@nvidia.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When creating a checkpoint of large models, the `checkpoint` action of
`cuda-checkpoint` can exceed the CRIU timeout. This causes CRIU to fail
with the following error, leaving the CUDA task in a locked state:
cuda_plugin: Checkpointing CUDA devices on pid 84145 restore_tid 84202
Error (criu/cr-dump.c:1791): Timeout reached. Try to interrupt: 0
Error (cuda_plugin.c:139): cuda_plugin: Unable to read output of cuda-checkpoint: Interrupted system call
Error (cuda_plugin.c:396): cuda_plugin: CHECKPOINT_DEVICES failed with
net: Unlock network
cuda_plugin: finished cuda_plugin stage 0 err -1
cuda_plugin: resuming devices on pid 84145
cuda_plugin: Restore thread pid 84202 found for real pid 84145
Unfreezing tasks into 1
Unseizing 84145 into 1
Error (criu/cr-dump.c:2111): Dumping FAILED.
To fix this, we set `task_info->checkpointed` before invoking
the `checkpoint` action to ensure that the CUDA task is resumed
even if CRIU times out.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Using libnftables the chain to lock the network is composed of
("CRIU-%d", real_pid). This leads to around 40 zdtm tests failing
with errors like this:
Error: No such file or directory; did you mean table 'CRIU-62' in family inet?
delete table inet CRIU-86
The reason is that as soon as a process is running in a namespace the
real PID can be anything and only the PID in the namespace is restored
correctly. Relying on the real PID does not work for the chain name.
Using the PID of the innermost namespace would lead to the chain be
called 'CRIU-1' most of the time which is also not really unique.
With this commit the change is now named using the already existing CRIU
run ID. To be able to correctly restore the process and delete the
locking table, the CRIU run id during checkpointing is now stored in the
inventory as dump_criu_run_id.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu_run_id will be used in upcoming changes to create and remove
network rules for network locking. Instead of trying to come up with
a way to create unique IDs, just use an existing library.
libuuid should be installed on most systems as it is indirectly required
by systemd (via libmount).
Signed-off-by: Adrian Reber <areber@redhat.com>
It creates a few timers with log expiration intervals, waites for C/R
and check that timers are armed and their intervals have been restored.
Signed-off-by: Austin Kuo <hsuanchikuo@gmail.com>
On aarch64 the test cmdlinenv00 was failing with:
FAIL: cmdlinenv00.c:120: auxv corrupted on restore (errno = 11 (Resource temporarily unavailable))
Starting with Linux kernel version 6.3 the size of AUXV was changed:
commit 28c8e088427ad30b4260953f3b6f908972b77c2d
Author: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Date: Wed Jan 4 14:20:54 2023 -0500
rseq: Increase AT_VECTOR_SIZE_BASE to match rseq auxvec entries
Two new auxiliary vector entries are introduced for rseq without
matching increment of the AT_VECTOR_SIZE_BASE, which causes failures
with CONFIG_HARDENED_USERCOPY=y.
Fixes: 317c8194e6ae ("rseq: Introduce feature size and alignment ELF auxiliary vector entries")
With this change AT_VECTOR_SIZE increases from 40 to 50 on aarch64. CRIU
uses AT_VECTOR_SIZE to read the content of /proc/PID/auxv
auxv_t mm_saved_auxv[AT_VECTOR_SIZE];
ret = read(fd, mm_saved_auxv, sizeof(mm_saved_auxv));
Now the tests works again on aarch64.
Signed-off-by: Adrian Reber <areber@redhat.com>
Running the zdtm/static/unlink_regular00 test on Ubuntu 24.04 on aarch64
results in following error:
# ./zdtm.py run -t zdtm/static/unlink_regular00 -k always
userns is supported
=== Run 1/1 ================ zdtm/static/unlink_regular00
==================== Run zdtm/static/unlink_regular00 in ns ====================
Skipping rtc at root
Start test
Test is SUID
./unlink_regular00 --pidfile=unlink_regular00.pid --outfile=unlink_regular00.out --dirname=unlink_regular00.test
Run criu dump
*** buffer overflow detected ***: terminated
############# Test zdtm/static/unlink_regular00 FAIL at CRIU dump ##############
Test output: ================================
<<< ================================
Send the 9 signal to 47
Wait for zdtm/static/unlink_regular00(47) to die for 0.100000
##################################### FAIL #####################################
According to the backtrace:
#0 __pthread_kill_implementation (threadid=281473158467616, signo=signo@entry=6, no_tid=no_tid@entry=0) at ./nptl/pthread_kill.c:44
#1 0x0000ffff93477690 in __pthread_kill_internal (signo=6, threadid=<optimized out>) at ./nptl/pthread_kill.c:78
#2 0x0000ffff9342cb3c in __GI_raise (sig=sig@entry=6) at ../sysdeps/posix/raise.c:26
#3 0x0000ffff93417e00 in __GI_abort () at ./stdlib/abort.c:79
#4 0x0000ffff9346abf0 in __libc_message_impl (fmt=fmt@entry=0xffff93552a78 "*** %s ***: terminated\n") at ../sysdeps/posix/libc_fatal.c:132
#5 0x0000ffff934e81a8 in __GI___fortify_fail (msg=msg@entry=0xffff93552a28 "buffer overflow detected") at ./debug/fortify_fail.c:24
#6 0x0000ffff934e79e4 in __GI___chk_fail () at ./debug/chk_fail.c:28
#7 0x0000ffff934e9070 in ___snprintf_chk (s=s@entry=0xffffc6ed04a3 "testfile", maxlen=maxlen@entry=4056, flag=flag@entry=2, slen=slen@entry=4053,
format=format@entry=0xaaaacffe3888 "link_remap.%d") at ./debug/snprintf_chk.c:29
#8 0x0000aaaacff4b8b8 in snprintf (__fmt=0xaaaacffe3888 "link_remap.%d", __n=4056, __s=0xffffc6ed04a3 "testfile")
at /usr/include/aarch64-linux-gnu/bits/stdio2.h:54
#9 create_link_remap (path=path@entry=0xffffc6ed2901 "/zdtm/static/unlink_regular00.test/subdir/testfile", len=len@entry=60, lfd=lfd@entry=20,
idp=idp@entry=0xffffc6ed14ec, nsid=nsid@entry=0xaaaada2bac00, parms=parms@entry=0xffffc6ed2808, fallback=0xaaaacff4c6c0 <dump_linked_remap+96>,
fallback@entry=0xffffc6ed2797) at criu/files-reg.c:1164
#10 0x0000aaaacff4c6c0 in dump_linked_remap (path=path@entry=0xffffc6ed2901 "/zdtm/static/unlink_regular00.test/subdir/testfile", len=len@entry=60,
parms=parms@entry=0xffffc6ed2808, lfd=lfd@entry=20, id=id@entry=12, nsid=nsid@entry=0xaaaada2bac00, fallback=fallback@entry=0xffffc6ed2797)
at criu/files-reg.c:1198
#11 0x0000aaaacff4d8b0 in check_path_remap (nsid=0xaaaada2bac00, id=12, lfd=20, parms=0xffffc6ed2808, link=<optimized out>) at criu/files-reg.c:1426
#12 dump_one_reg_file (lfd=20, id=12, p=0xffffc6ed2808) at criu/files-reg.c:1827
#13 0x0000aaaacff51078 in dump_one_file (pid=<optimized out>, fd=4, lfd=20, opts=opts@entry=0xaaaada2ba2c0, ctl=ctl@entry=0xaaaada2c4d50,
e=e@entry=0xffffc6ed39c8, dfds=dfds@entry=0xaaaada2c3d40) at criu/files.c:581
#14 0x0000aaaacff5176c in dump_task_files_seized (ctl=ctl@entry=0xaaaada2c4d50, item=item@entry=0xaaaada2b8f80, dfds=dfds@entry=0xaaaada2c3d40)
at criu/files.c:657
#15 0x0000aaaacff3d3c0 in dump_one_task (parent_ie=0x0, item=0xaaaada2b8f80) at criu/cr-dump.c:1679
#16 cr_dump_tasks (pid=<optimized out>) at criu/cr-dump.c:2224
#17 0x0000aaaacff163a0 in main (argc=<optimized out>, argv=0xffffc6ed40e8, envp=<optimized out>) at criu/crtools.c:293
This line is the problem:
snprintf(tmp + 1, sizeof(link_name) - (size_t)(tmp - link_name - 1), "link_remap.%d", rfe.id);
The problem was that the `-1` was on the inside of the braces and not on
the outside. This way the destination size was increase by 1 instead of
being decreased by 1 which triggered the buffer overflow detection.
Signed-off-by: Adrian Reber <areber@redhat.com>
Based on the code, the `ret` variable at this point does not
represent the task state, so this log message should be
moved to a position after the `compel_wait_task()` function.
Signed-off-by: Yuanhong Peng <yummypeng@linux.alibaba.com>
When using the nftables network locking backend and restoring a process
a second time the network locking has already been deleted by the first
restore. The second restore will print out to the console text like:
Error: Could not process rule: No such file or directory
delete table inet CRIU-202621
With this change CRIU's log FD is used by libnftables stdout and stderr.
Signed-off-by: Adrian Reber <areber@redhat.com>
Cgroup v1 freezer has always been problematic, failing to freeze a
cgroup.
In runc, we have implemented a few kludges to increase the chance of
succeeding, but those are used when runc freezes a cgroup for its own
purposes (for "runc pause" and to modify device properties for cgroup
v1).
When criu is used, it fails to freeze a cgroup from time to time
(see [1], [2]). Let's try adding kludges similar to ones in runc.
Alas, I have absolutely no way to test this, so please review carefully.
[1]: https://github.com/opencontainers/runc/issues/4273
[2]: https://github.com/opencontainers/runc/issues/4457
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
There are a few issues with the freeze_processes logic:
1. Commit 9fae23fbe2 grossly (by 1000x) miscalculated the number of
attempts required, as a result, we are seeing something like this:
> (00.000340) freezing processes: 100000 attempts with 100 ms steps
> (00.000351) freezer.state=THAWED
> (00.000358) freezer.state=FREEZING
> (00.100446) freezer.state=FREEZING
> ...close to 100 lines skipped...
> (09.915110) freezer.state=FREEZING
> (10.000432) Error (criu/cr-dump.c:1467): Timeout reached. Try to interrupt: 0
> (10.000563) freezer.state=FREEZING
For 10s with 100ms steps we only need 100 attempts, not 100000.
2. When the timeout is hit, the "failed to freeze cgroup" error is not
printed, and the log_unfrozen_stacks is not called either.
3. The nanosleep at the last iteration is useless (this was hidden by
issue 1 above, as the timeout was hit first).
Fix all these.
While at it,
4. Amend the error message with the number of attempts, sleep duration,
and timeout.
5. Modify the "freezing cgroup" debug message to be in sync with the
above error.
Was:
> freezing processes: 100000 attempts with 100 ms steps
Now:
> freezing cgroup some/name: 100 x 100ms attempts, timeout: 10s
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The kernel releases a test socket asynchronously, so the restore can
fail if it is executed before the kernel actually destroys the socket.
Fixes#2537
Signed-off-by: Andrei Vagin <avagin@google.com>
Right now, this test fails with this error:
Error (criu/files-reg.c:1031): Can't dump ghost file
/criu/test/javaTests/omrvmem_000000626_Mlm48x of 2097152 size,
increase limit
Signed-off-by: Andrei Vagin <avagin@google.com>
cuda-checkpoint returns the positive CUDA error code when it runs into an issue
and passing that along as the return value would cause errors to get ignored
Signed-off-by: Jesus Ramos <jeramos@nvidia.com>
The vvar_vclock was introduced by [1]. Basically, the old vvar vma has
been splited on two parts. In term of C/R, these two vma-s can be still
treated as one.
[1] e93d2521b27f ("x86/vdso: Split virtual clock pages into dedicated mapping")
Signed-off-by: Andrei Vagin <avagin@google.com>
Fix for the following error when building CRIU on Rocky Linux 8
criu/pidfd.c: In function ‘pidfd_open’:
criu/pidfd.c:119:17: error: ‘__NR_pidfd_open’ undeclared (first use in this function); did you mean ‘pidfd_open’?
return syscall(__NR_pidfd_open, pid, flags);
^~~~~~~~~~~~~~~
pidfd_open
criu/pidfd.c:119:17: note: each undeclared identifier is reported only once for each function it appears in
criu/pidfd.c:120:1: error: control reaches end of non-void function [-Werror=return-type]
}
^
criu/pidfd.c: At top level:
cc1: error: unrecognized command line option ‘-Wno-unknown-warning-option’ [-Werror]
cc1: error: unrecognized command line option ‘-Wno-dangling-pointer’ [-Werror]
cc1: all warnings being treated as errors
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
We need to dynamically calculate TASK_SIZE depending
on the MMU on RISC-V system. [We are using analogical
approach on aarch64/ppc64le.]
This change was tested on physical machine:
StarFive VisionFive 2
isa : rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd_zba_zbb
mmu : sv39
uarch : sifive,u74-mc
mvendorid : 0x489
marchid : 0x8000000000000007
mimpid : 0x4210427
hart isa : rv64imafdc_zicntr_zicsr_zifencei_zihpm_zca_zcd_zba_zbb
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
We don't need to have compel/arch/riscv64/plugins/std/syscalls/syscalls.S
tracked in git. It is autogenerated. We also need to update our .gitignore
to ignore autogenerated files with syscall tables.
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
If a CUDA process is already in a "locked" or "checkpointed" state
during criu dump, the CUDA plugin currently fails with an error because
it attempts an unnecessary "lock" action using the cuda-checkpoint tool.
This patch extends the CUDA plugin to handle such cases by first
verifying the initial state of the CUDA processes and skipping
unnecessary "lock" and "checkpoint" actions when a process has been
locked or checkpointed before CRIU is invoked.
In particular, CUDA tasks may already be in a "locked" or "checkpointed"
state to ensure consistent checkpoint/restore for distributed workloads,
such as model training, where multiple containers run across different
cluster nodes.
Another use case for this functionality is optimizing resource
utilization, where CUDA tasks with low-priority are preempted
immediately to release GPU resources needed by high-priority
tasks, and the paused workloads are later resumed or migrated
to another node.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
We have multiple processes open a pidfd to a common dead process.
After C/R we check that the inode numbers for these pidfds are equal or
not.
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Currently, the `waitpid()` call on the tmp process can be made by a
process which is not its parent. This causes restore to fail.
This patch instead selects one process to create the tmp process and
open all the fds that point to it. These fds are sent to the correct
process(es).
Fixes: #2496
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
The check for `/dev/nvidiactl` to determine if the CUDA plugin can be
used is unreliable because in some cases the default path for driver
installation is different [1]. This patch changes the logic to check
if a GPU device is available in `/proc/driver/nvidia/gpus/`. This
approach is similar to `torch.cuda.is_available()` and it is a more
accurate indicator.
The subsequent check for support of the `cuda-checkpoint --action`
option would confirm if the driver supports checkpoint/restore.
[1] https://github.com/NVIDIA/gpu-operatorFixes: #2509
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Container runtimes like CRI-O and containerd utilize the freezer cgroup
to create a consistent snapshot of container root filesystem (rootfs)
changes. In this case, the container is frozen before invoking CRIU.
After CRIU successfully completes, a copy of the container rootfs diff
is saved, and the container is then unfrozen.
However, the `cuda-checkpoint` tool is not able to perform a 'lock'
action on frozen threads. To support GPU checkpointing with these
container runtimes, we need to unfreeze the cgroup and return it to its
original state once the checkpointing is complete.
To reflect this new behavior, the following changes are applied:
- `dont_use_freeze_cgroup(void)` -> `set_compel_interrupt_only_mode(void)`
- `bool freeze_cgroup_disabled` -> `bool compel_interrupt_only_mode`
- `check_freezer_cgroup(void)` -> `prepare_freezer_for_interrupt_only_mode(void)`
Note that when `compel_interrupt_only_mode` is set to `true`,
`compel_interrupt_task()` is used instead of `freeze_processes()`
to prevent tasks from running during `criu dump`.
Fixes: #2508
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When `check_freezer_cgroup()` has non-zero return value, `goto err` calls
`return ret`. However, the value of `ret` has been set to `0` in the lines
above and CRIU does not handle the error properly.
This problem is related to https://github.com/checkpoint-restore/criu/issues/2508
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When restoring dumps in new mount + pid namespaces where multiple dumps
share the same network namespace, CRIU may fail due to conflicting
unix socket names. This happens because the service worker creates
sockets using a pattern that includes criu_run_id, but util_init()
is called after cr_service_work() starts.
The socket naming pattern "crtools-fd-%d-%d" uses the restore PID
and criu_run_id, however criu_run_id is always 0 when not initialized,
leading to conflicts when multiple restores run simultaneously either
in the same CRIU process or because of multiple CRIU processes
doing the same operation in different PID namespaces.
Fix this by:
- Moving util_init() before cr_service_work() starts
- Adding a second util_init() call in the service worker fork
to ensure unique IDs across multiple worker runs
- Making sure that dump and restore operations have util_init() called
early to generate unique socket names
With this fix, socket names always include the namespace ID, preventing
conflicts when multiple processes with the same pid share a network
namespace.
Fixes#2499
[ avagin: minore code changes ]
Signed-off-by: Lorenzo Fontana <fontanalorenz@gmail.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
After a fork, both the child and parent processes may trigger a page fault (#PF)
at the same virtual address, referencing the same position in the page image.
If deduplication is enabled, the last process to trigger the page fault will fail.
Therefore, deduplication should be disabled after a fork to prevent this issue.
Signed-off-by: Liu Hua <weldonliu@tencent.com>
This patch blocks SIGCHLD during temporary process creation to prevent a
race condition between kill() and waitpid() where sigchld_handler()
causes `criu restore` to fail with an error.
Fixes: #2490
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch adds two test plugins to verify that CRIU plugins listed
in the inventory image are enabled, while those that are not listed
can be disabled.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch extends the inventory image with a `plugins` field that
contains an array of plugins which were used during checkpoint,
for example, to save GPU state. In particular, the CUDA and AMDGPU
plugins are added to this field only when the checkpoint contains
GPU state. This allows to disable unnecessary plugins during restore,
show appropriate error messages if required CRIU plugin are missing,
and migrate a process that does not use GPU from a GPU-enabled system
to CPU-only environment.
We use the `optional plugins_entry` for backwards compatibility. This
entry allows us to distinguish between *unset* and *missing* field:
- When the field is missing, it indicates that the checkpoint was
created with a previous version of CRIU, and all plugins should be
*enabled* during restore.
- When the field is empty, it indicates that no plugins were used during
checkpointing. Thus, all plugins can be *disabled* during restore.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch fixes the following errors reported by ruff:
lib/pycriu/images/pb2dict.py:307:24: E721 Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks
|
305 | elif field.type in _basic_cast:
306 | cast = _basic_cast[field.type]
307 | if pretty and (cast == int):
| ^^^^^^^^^^^ E721
308 | if is_hex:
309 | # Fields that have (criu).hex = true option set
|
lib/pycriu/images/pb2dict.py:379:13: E721 Use `is` and `is not` for type comparisons, or `isinstance()` for isinstance checks
|
377 | elif field.type in _basic_cast:
378 | cast = _basic_cast[field.type]
379 | if (cast == int) and is_string(value):
| ^^^^^^^^^^^ E721
380 | if _marked_as_dev(field):
381 | return encode_dev(field, value)
|
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
We open a pidfd to a thread using `PIDFD_THREAD` flag and after C/R
ensure that we can send signals using it with `PIDFD_SIGNAL_THREAD`.
signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
After, C/R of pidfds that point to dead processes their inodes might
change. But if two pidfds point to same dead process they should
continue to do so after C/R.
This test ensures that this happens by calling `statx()` on pidfds after
C/R and then comparing their inode numbers.
Support for comparing pidfds by using `statx()` and inode numbers was
introduced alongside pidfs. So if `f_type` of pidfd is not equal to
`PID_FS_MAGIC` then we skip this test.
signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Validate that pidfds can been used to send signals to different
processes after C/R using the `pidfd_send_signal()` syscall.
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
Process file descriptors (pidfds) were introduced to provide a stable
handle on a process. They solve the problem of pid recycling.
For a detailed explanation, see https://lwn.net/Articles/801319/ and
http://www.corsix.org/content/what-is-a-pidfd
Before Linux 6.9, anonymous inodes were used for the implementation of
pidfds. So, we detect them in a fashion similiar to other fd types that
use anonymous inodes by calling `readlink()`.
After 6.9, pidfs (a file system for pidfds) was introduced.
In 6.9 `S_ISREG()` returned true for pidfds, but this again changed with
6.10.
(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/fs/pidfs.c?h=v6.11-rc2#n285)
After this change, pidfs inodes have no file type in st_mode in
userspace.
We use `PID_FS_MAGIC` to detect pidfds for kernel >= 6.9
Hence, check for pidfds occurs before the check for regular files.
For pidfds that refer to dead processes, we lose the pid of the process
as the Pid and NSpid fields in /proc/<pid>/fdinfo/<pidfd> change to -1.
So, we create a temporary process for each unique inode and open pidfds
that refer to this process. After all pidfds have been opened we kill
this temporary process.
This commit does not include support for pidfds that point to a specific
thread, i.e pidfds opened with `PIDFD_THREAD` flag.
Fixes: #2258
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
We only use the last pid from the list in NSpid entry (from
/proc/<pid>/fdinfo/<pidfd>) while restoring pidfds.
The last pid refers to the pid of the process in the most deeply nested
pid namespace. Since CRIU does not currently support nested pid
namespaces, this entry is the one we want.
After Linux 6.9, inode numbers can be used to compare pidfds. pidfds
referring to the same process will have the same inode numbers. We use
inode numbers to restore pidfds that point to dead processes.
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
By default, CRIU uses the path "/usr/lib/criu" to install and load
plugins at runtime. This path is defined by the `PLUGINDIR` variable
in Makefile.install and `CR_PLUGIN_DEFAULT` in `criu/include/plugin.h`.
However, some distribution packages might install the CRIU plugins at
"/usr/lib64/criu" instead. This patch updates the makefile to align
the path defined by `CR_PLUGIN_DEFAULT` with the value of `PLUGINDIR`.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch fixes the following warnings that appear
when building an RPM package:
+ /usr/lib/rpm/redhat/brp-mangle-shebangs
*** WARNING: ./usr/src/debug/criu-4.0-1.fc42.x86_64/plugins/amdgpu/amdgpu_plugin_util.c is executable but has no shebang, removing executable bit
*** WARNING: ./usr/src/debug/criu-4.0-1.fc42.x86_64/plugins/amdgpu/amdgpu_plugin_util.h is executable but has no shebang, removing executable bit
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Major changes:
* CUDA plugin to support checkpointing and restoring NVIDIA CUDA applications.
* Shadow stack support
* Pagemap cache: Added support for PAGEMAP_SCAN ioctl
The full changelog can be found here: https://criu.org/Download/criu/4.0.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The topology parsing assumed that all parameter names were
30 characters or fewer, but
recommended_sdma_engine_id_mask
is 31 characters.
Make the maximum length a macro, and set it to 64.
Signed-off-by: David Francis <David.Francis@amd.com>
The presence of /dev/nvidiactl indicates that the system has a
compatible NVIDIA GPU driver installed and that the GPU is accessible to
the operating system.
Signed-off-by: Andrei Vagin <avagin@google.com>
Some plugins (e.g., CUDA) may not function correctly when processes are
frozen using cgroups. This change introduces a mechanism to disable the
use of freeze cgroups during process seizing, even if explicitly
requested via the --freeze-cgroup option.
The CUDA plugin is updated to utilize this new mechanism to ensure
compatibility.
Signed-off-by: Andrei Vagin <avagin@google.com>
This patch fixes the following typos reported by codespell:
./test/others/bers/bers.c:394: dependin ==> depending, depend in
./criu/kerndat.c:837: hitted ==> hit
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The `uninstall_module.py` script is a wrapper for the `pip uninstall`
command that enables support for specifying installation prefix
(i.e., `--prefix`). When this functionality is used, we intentionally
set `sys.path` to include only search paths for the specified prefix
to avoid unintentional uninstallation of packages in system paths.
Since `importlib_metadata` version 8.1.0, the `Distribution.from_name()`
method has been modified [1] to perform additional pre-processing of
Distribution objects [2] that requires loading distribution metadata
and results in the following error:
File "/usr/local/lib/python3.12/site-packages/importlib_metadata/__init__.py", line 422, in <lambda>
buckets = bucket(dists, lambda dist: bool(dist.metadata))
^^^^^^^^^^^^^
File "/usr/local/lib/python3.12/site-packages/importlib_metadata/__init__.py", line 454, in metadata
from . import _adapters
File "/usr/local/lib/python3.12/site-packages/importlib_metadata/_adapters.py", line 3, in <module>
import email.message
File "/usr/lib64/python3.12/email/message.py", line 11, in <module>
import quopri
ModuleNotFoundError: No module named 'quopri'
This error occurs because we have excluded system paths from the list
of search paths (`sys.path`).
However, this pre-processing is not required for our use case, as we
only use the discovery mechanism of importlib_metadata to resolve the
metadata directory path of the module being uninstalled.
To fix this problem, this patch updates `uninstall_module` to avoid the
`from_name()` method and use `discover(name=package_name)` directly.
[1] a65c29adc0
[2] a65c29ad/importlib_metadata/__init__.py (L391)Fixes: #2468
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When attempting to checkpoint a container with CUDA processes,
CRIU could fail with the following error:
Error (criu/cr-dump.c:1791): Timeout reached. Try to interrupt: 1
Error (cuda_plugin.c:143): cuda_plugin: Unable to read output of cuda-checkpoint: Interrupted system call
Error (cuda_plugin.c:384): cuda_plugin: PAUSE_DEVICES failed with
In this situation, the target process is locked, but CRIU fails due to
a timeout and exits with an error. We need to make sure that the target
PID is unlocked in such case.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Some test environments (Actuated runners for example) do not support
maclvan devices. Skip tests depending on it automatically.
Signed-off-by: Adrian Reber <areber@redhat.com>
Previously the check was just if /sys/fs/selinux is mounted. This
extends the check to see if all necessary tools are installed.
Signed-off-by: Adrian Reber <areber@redhat.com>
Running 'crit x ./ rss' on aarch64 crashes with:
File "/home/criu/crit/crit/__main__.py", line 331, in explore_rss
while vmas[vmi]['start'] < pme:
~~~~^^^^^
IndexError: list index out of range
This adds an additional check to the while loop to do access indexes out
of range.
Signed-off-by: Adrian Reber <areber@redhat.com>
Errors on aarch64:
In file included from amdgpu_plugin_drm.h:10,
from amdgpu_plugin.c:33:
amdgpu_plugin.c: In function 'amdgpu_plugin_dump_file':
amdgpu_plugin_util.h:24:20: error: format '%lld' expects argument of type 'long long int', but argument 6 has type '__u64' {aka 'long unsigned int'} [-Werror=format=]
24 | #define LOG_PREFIX "amdgpu_plugin: "
| ^~~~~~~~~~~~~~~~~
../../criu/include/log.h:47:52: note: in expansion of macro 'LOG_PREFIX'
47 | #define pr_info(fmt, ...) print_on_level(LOG_INFO, LOG_PREFIX fmt, ##__VA_ARGS__)
| ^~~~~~~~~~
amdgpu_plugin.c:1236:9: note: in expansion of macro 'pr_info'
1236 | pr_info("devices:%d bos:%d objects:%d priv_data:%lld\n", args.num_devices, args.num_bos, args.num_objects,
| ^~~~~~~
cc1: all warnings being treated as errors
Errors on ppc64:
In file included from amdgpu_plugin_drm.h:10,
from amdgpu_plugin.c:33:
amdgpu_plugin.c: In function 'amdgpu_plugin_dump_file':
amdgpu_plugin_util.h:24:20: error: format '%llu' expects argument of type 'long long unsigned int', but argument 6 has type '__u64' {aka 'long unsigned int'} [-Werror=format=]
24 | #define LOG_PREFIX "amdgpu_plugin: "
| ^~~~~~~~~~~~~~~~~
../../criu/include/log.h:47:52: note: in expansion of macro 'LOG_PREFIX'
47 | #define pr_info(fmt, ...) print_on_level(LOG_INFO, LOG_PREFIX fmt, ##__VA_ARGS__)
| ^~~~~~~~~~
amdgpu_plugin.c:1236:9: note: in expansion of macro 'pr_info'
1236 | pr_info("devices:%u bos:%u objects:%u priv_data:%llu\n",
| ^~~~~~~
cc1: all warnings being treated as errors
In file included from amdgpu_plugin_util.c:38:
amdgpu_plugin_util.c: In function 'print_kfd_bo_stat':
amdgpu_plugin_util.h:24:20: error: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type '__u64' {aka 'long unsigned int'} [-Werror=format=]
24 | #define LOG_PREFIX "amdgpu_plugin: "
| ^~~~~~~~~~~~~~~~~
../../criu/include/log.h:47:52: note: in expansion of macro 'LOG_PREFIX'
47 | #define pr_info(fmt, ...) print_on_level(LOG_INFO, LOG_PREFIX fmt, ##__VA_ARGS__)
| ^~~~~~~~~~
amdgpu_plugin_util.c:196:17: note: in expansion of macro 'pr_info'
196 | pr_info("%s(), %d. KFD BO Addr: %llx \n", __func__, idx, bo->addr);
| ^~~~~~~
amdgpu_plugin_util.h:24:20: error: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type '__u64' {aka 'long unsigned int'} [-Werror=format=]
24 | #define LOG_PREFIX "amdgpu_plugin: "
| ^~~~~~~~~~~~~~~~~
../../criu/include/log.h:47:52: note: in expansion of macro 'LOG_PREFIX'
47 | #define pr_info(fmt, ...) print_on_level(LOG_INFO, LOG_PREFIX fmt, ##__VA_ARGS__)
| ^~~~~~~~~~
amdgpu_plugin_util.c:197:17: note: in expansion of macro 'pr_info'
197 | pr_info("%s(), %d. KFD BO Size: %llx \n", __func__, idx, bo->size);
| ^~~~~~~
amdgpu_plugin_util.h:24:20: error: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type '__u64' {aka 'long unsigned int'} [-Werror=format=]
24 | #define LOG_PREFIX "amdgpu_plugin: "
| ^~~~~~~~~~~~~~~~~
../../criu/include/log.h:47:52: note: in expansion of macro 'LOG_PREFIX'
47 | #define pr_info(fmt, ...) print_on_level(LOG_INFO, LOG_PREFIX fmt, ##__VA_ARGS__)
| ^~~~~~~~~~
amdgpu_plugin_util.c:198:17: note: in expansion of macro 'pr_info'
198 | pr_info("%s(), %d. KFD BO Offset: %llx \n", __func__, idx, bo->offset);
| ^~~~~~~
amdgpu_plugin_util.h:24:20: error: format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type '__u64' {aka 'long unsigned int'} [-Werror=format=]
24 | #define LOG_PREFIX "amdgpu_plugin: "
| ^~~~~~~~~~~~~~~~~
../../criu/include/log.h:47:52: note: in expansion of macro 'LOG_PREFIX'
47 | #define pr_info(fmt, ...) print_on_level(LOG_INFO, LOG_PREFIX fmt, ##__VA_ARGS__)
| ^~~~~~~~~~
amdgpu_plugin_util.c:199:17: note: in expansion of macro 'pr_info'
199 | pr_info("%s(), %d. KFD BO Restored Offset: %llx \n", __func__, idx, bo->restored_offset);
| ^~~~~~~
cc1: all warnings being treated as errors
Co-developed-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Skip cross-compilation on armv7 because, among many other errors,
it fails with the following:
In file included from ../../include/common/lock.h:9,
from ../../criu/include/files.h:9,
from amdgpu_plugin.c:30:
../../include/common/asm/atomic.h:60:2: error: #error ARM architecture version (CONFIG_ARMV*) not set or unsupported.
60 | #error ARM architecture version (CONFIG_ARMV*) not set or unsupported.
| ^~~~~
../../include/common/asm/atomic.h: In function 'atomic_add_return':
../../include/common/asm/atomic.h:81:9: error: implicit declaration of function 'smp_mb' [-Werror=implicit-function-declaration]
81 | smp_mb();
| ^~~~~~
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
To enable cross-compile we need to use the CC definition from
criu/scripts/nmk/scripts/tools.mk:
CC := $(CROSS_COMPILE)$(HOSTCC)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Here is an example how to run one test:
$ python test/zdtm.py run -t zdtm/static/env00 --ignore-taint --mocked-cuda-checkpoint
Signed-off-by: Andrei Vagin <avagin@google.com>
1. os auto assignment vma addr maybe conflict with vma in gpu living migrate scene;
2. so, we should give choice to user;
Signed-off-by: haozi007 <liuhao27@huawei.com>
New internal glibc types __timeval64 [1] and __suseconds64_t [2] have
been introduced as a solution for the Y2038 problem [3]. These 64-bit
types are used across all architectures. However, this change causes
the following build errors when cross-compiling on ARMv7 (armhf):
criu/timer.c:49:17: error: format '%ld' expects argument of type 'long int', but argument 5 has type '__suseconds64_t' {aka 'long long int'} [-Werror=format=]
49 | pr_info("Restored %s timer to %" PRId64 ".%ld -> %" PRId64 ".%ld\n", n,
| ^~~~~~~~~~~~~~~~~~~~~~~~
50 | (int64_t)val->it_value.tv_sec, val->it_value.tv_usec,
| ~~~~~~~~~~~~~~~~~~~~~
| |
| __suseconds64_t {aka long long int}
criu/timer.c:49:17: error: format '%ld' expects argument of type 'long int', but argument 7 has type '__suseconds64_t' {aka 'long long int'} [-Werror=format=]
49 | pr_info("Restored %s timer to %" PRId64 ".%ld -> %" PRId64 ".%ld\n", n,
| ^~~~~~~~~~~~~~~~~~~~~~~~
50 | (int64_t)val->it_value.tv_sec, val->it_value.tv_usec,
51 | (int64_t)val->it_interval.tv_sec, val->it_interval.tv_usec);
| ~~~~~~~~~~~~~~~~~~~~~~~~
| |
| __suseconds64_t {aka long long int}
ns.c:234:48: error: format '%ld' expects argument of type 'long int', but argument 5 has type 'time_t' {aka 'long long int'} [-Werror=format=]
234 | len = snprintf(buf, sizeof(buf), "%d %ld 0", clk_id, offset);
| ~~^ ~~~~~~
| | |
| long int time_t {aka long long int}
| %lld
msg.c:58:41: error: format '%ld' expects argument of type 'long int', but argument 3 has type '__suseconds64_t' {aka 'long long int'} [-Werror=format=]
58 | off += sprintf(buf + off, ".%.3ld: ", tv.tv_usec / 1000);
| ~~~~^ ~~~~~~~~~~~~~~~~~
| | |
| long int __suseconds64_t {aka long long int}
| %.3lld
../lib/zdtmtst.h:137:26: error: format '%ld' expects argument of type 'long int', but argument 4 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
137 | test_msg("ERR: %s:%d: " format " (errno = %d (%s))\n", __FILE__, __LINE__, ##arg, errno, \
| ^~~~~~~~~~~~~~
pthread_timers_h.c:72:17: note: in expansion of macro 'pr_perror'
72 | pr_perror("wrong interval: %ld:%ld", itimerspec.it_interval.tv_sec, itimerspec.it_interval.tv_nsec);
| ^~~~~~~~~
vdso00.c:22:32: error: format '%li' expects argument of type 'long int', but argument 3 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
22 | test_msg("%d time: %10li\n", getpid(), tv.tv_sec);
| ~~~~^ ~~~~~~~~~
| | |
| long int __time64_t {aka long long int}
| %10lli
vdso00.c:29:32: error: format '%li' expects argument of type 'long int', but argument 3 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
29 | test_msg("%d time: %10li\n", getpid(), tv.tv_sec);
| ~~~~^ ~~~~~~~~~
| | |
| long int __time64_t {aka long long int}
| %10lli
vdso01.c:357:42: error: format '%li' expects argument of type 'long int', but argument 2 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
357 | test_msg("gettimeofday: tv_sec %li vdso_gettimeofday: tv_sec %li\n", tv1.tv_sec, tv2.tv_sec);
| ~~^ ~~~~~~~~~~
| | |
| long int __time64_t {aka long long int}
| %lli
vdso01.c:357:72: error: format '%li' expects argument of type 'long int', but argument 3 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
357 | test_msg("gettimeofday: tv_sec %li vdso_gettimeofday: tv_sec %li\n", tv1.tv_sec, tv2.tv_sec);
| ~~^ ~~~~~~~~~~
| | |
| long int __time64_t {aka long long int}
|
vdso01.c:328:43: error: format '%li' expects argument of type 'long int', but argument 2 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
328 | test_msg("clock_gettime: tv_sec %li vdso_clock_gettime: tv_sec %li\n", ts1.tv_sec, ts2.tv_sec);
| ~~^ ~~~~~~~~~~
| | |
| long int __time64_t {aka long long int}
| %lli
vdso01.c:328:74: error: format '%li' expects argument of type 'long int', but argument 3 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
328 | test_msg("clock_gettime: tv_sec %li vdso_clock_gettime: tv_sec %li\n", ts1.tv_sec, ts2.tv_sec);
| ~~^ ~~~~~~~~~~
| | |
| long int __time64_t {aka long long int}
|
../lib/zdtmtst.h:144:26: error: format '%ld' expects argument of type 'long int', but argument 4 has type 'time_t' {aka 'long long int'} [-Werror=format=]
144 | test_msg("FAIL: %s:%d: " format " (errno = %d (%s))\n", __FILE__, __LINE__, ##arg, errno, \
| ^~~~~~~~~~~~~~~
mtime_mmap.c:80:17: note: in expansion of macro 'fail'
80 | fail("mtime %ld wasn't updated on mmapped %s file", mtime_new, filename);
| ^~~~
../lib/zdtmtst.h:144:26: error: format '%ld' expects argument of type 'long int', but argument 4 has type '__time64_t' {aka 'long long int'} [-Werror=format=]
144 | test_msg("FAIL: %s:%d: " format " (errno = %d (%s))\n", __FILE__, __LINE__, ##arg, errno, \
| ^~~~~~~~~~~~~~~
mtime_mmap.c:101:17: note: in expansion of macro 'fail'
101 | fail("After migration, mtime changed to %ld", fst.st_mtime);
| ^~~~
[1] https://sourceware.org/git/?p=glibc.git;h=504c98717062cb9bcbd4b3e59e932d04331ddca5
[2] https://sourceware.org/git/?p=glibc.git;h=3fced064f23562ec24f8312ffbc14950993969e6
[3] https://en.wikipedia.org/wiki/Year_2038_problem
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
By default, if the "CRIU_LIBS_DIR" environment variable is not set,
CRIU will load all plugins installed in `/usr/lib/criu`. This may
result in running the ZDTM tests with plugins for a different version
of CRIU (e.g., installed from a package).
This patch updates ZDTM to always set the "CRIU_LIBS_DIR" environment
variable and use a local "plugins" directory. This directory contains
copies of the plugin files built from source. In addition, this patch
adds the `--criu-plugin` option to the `zdtm.py run` command, allowing
tests to be run with specified CRIU plugins.
Example:
- Run test only with AMDGPU plugin
./zdtm.py run -t zdtm/static/busyloop00 --criu-plugin amdgpu
- Run test only with CUDA plugin
./zdtm.py run -t zdtm/static/busyloop00 --criu-plugin cuda
- Run test with both AMDGPU and CUDA plugins
./zdtm.py run -t zdtm/static/busyloop00 --criu-plugin amdgpu cuda
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When the cuda-checkpoint tool is not installed, execvp() is expected to
fail and return -1. In this case, we need to call exit() to terminate
the child process that was created earlier with fork().
Since CRIU can be used with applications that do not use CUDA, even
when the CUDA plugin is installed, this patch also updates the log
messages to show debug and warning (instead of error) when the
cuda-checkpoint tool is not found in $PATH.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Signed-off-by: Andrei Vagin <avagin@google.com>
Show information about mounts available on the host filesystem.
This is useful for debugging.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIU provides two plugins for checkpoint/restore of GPU applications:
amdgpu and cuda. Both plugins use the `RESUME_DEVICES_LATE` hook to
enable restore:
CR_PLUGIN_REGISTER_HOOK(CR_PLUGIN_HOOK__RESUME_DEVICES_LATE, amdgpu_plugin_resume_devices_late)
CR_PLUGIN_REGISTER_HOOK(CR_PLUGIN_HOOK__RESUME_DEVICES_LATE, cuda_plugin_resume_devices_late)
However, CRIU currently does not support running more than one plugin
for the same hook. As a result, when both plugins are installed, the
resume function for CUDA applications is not executed. To fix this,
we need to make sure that both `plugin_resume_devices_late()` functions
return `-ENOTSUP` when restore is not supported.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The plugin hook "PAUSE_DEVICES" was recently introduced in the following
commit. This hook was intended to execute the cuda-checkpoint tool
before the process tree is frozen. However, the run_plugins() call has
been placed immediately *after* freeze_processes(). This causes the
cuda-checkpoint tool to hang indefinitely during the checkpointing
of CUDA applications running in containers, eventually leading to its
termination by the timeout alarm.
a85f488595
criu/plugin: Introduce new plugin hooks PAUSE_DEVICES and CHECKPOINT_DEVICES to be used during pstree collection
This problem can be reproduced with the following example:
sudo podman run -d --rm \
--device nvidia.com/gpu=all --security-opt=label=disable \
quay.io/radostin/cuda-counter
sudo podman container checkpoint -l -e /tmp/checkpoint.tar
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
For historical reasons, some tools like rpm [1] or ldd [2,3]
may expect the executable bit to be present for the correct
identification of shared libraries. The executable bit on .so
files is set by default by compilers (e.g., GCC). It is not
strictly necessary but primarily a convention.
[1] https://docs.fedoraproject.org/en-US/package-maintainers/CommonRpmlintIssues/#unstripped_binary_or_object
[2] https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/ldd.bash.in;h=d6b640df;hb=HEAD#l154
[3] $ sudo ldd /usr/lib/criu/*.so
/usr/lib/criu/amdgpu_plugin.so:
ldd: warning: you do not have execution permission for `/usr/lib/criu/amdgpu_plugin.so'
linux-vdso.so.1 (0x00007fd0a2a3e000)
libdrm.so.2 => /lib64/libdrm.so.2 (0x00007fd0a29eb000)
libdrm_amdgpu.so.1 => /lib64/libdrm_amdgpu.so.1 (0x00007fd0a29de000)
libc.so.6 => /lib64/libc.so.6 (0x00007fd0a27fc000)
/lib64/ld-linux-x86-64.so.2 (0x00007fd0a2a40000)
/usr/lib/criu/cuda_plugin.so:
ldd: warning: you do not have execution permission for `/usr/lib/criu/cuda_plugin.so'
linux-vdso.so.1 (0x00007f1806e13000)
libc.so.6 => /lib64/libc.so.6 (0x00007f1806c08000)
/lib64/ld-linux-x86-64.so.2 (0x00007f1806e15000)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch updates the dependencies section of the AMDGPU plugin man
page to reflect that the plugin has been merged upstream and to fix a
formatting issue.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
In commit 2e456ccf0c34a056e3ccafac4a0c7effef14d918 ("Linux: Make
__rseq_size useful for feature detection (bug 31965)") glibc 2.40
changed the meaning of __rseq_size slightly: it is now the size
of the active/feature area (20 bytes initially), and not the size
of the entire initially defined struct (32 bytes including padding).
The reason for the change is that the size including padding does not
allow detection of newly added features while previously unused
padding is consumed.
The prep_libc_rseq_info change in criu/cr-restore.c is not necessary
on kernels which have full ptrace support for obtaining rseq
information because the code is not used. On older kernels, it is
a correctness fix because with size 20 (the new value), rseq
registeration would fail.
The two other changes are required to make rseq unregistration work
in tests.
Signed-off-by: Florian Weimer <fweimer@redhat.com>
cgroup testcases live in the same cgroup root zdtmtst and
zdtmtst.defaultroot controller then create child subgroup for testing. This
can cause problems when cgroup testcases run in parallel. For example,
testcase A dumps the child subgroup of testcase B since it's in the cgroup
root but in the middle of restoring of testcase A, testcase B completes and
cleans up the subgroup directory. This causes error in testcase A restore.
This commit adds excl flag to all cgroup testcases description so that
these don't run parallel.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
The CI tests with CentOS 7 have been disabled and removed [1,2].
This patch removes the obsolete Makefile targets for these tests.
[1] 24bc083653
[2] f8466ca798
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Sometimes due to sigblockmask inheritance cgroupd can inherit SIGTERM
blocked. That will lead cgroupd ignoring SIGTERM from stop_cgroupd() and
CRIU will get stuck due to waiting for never-stopping cgroupd.
I see this happening in lxc-checkpoint, also saw this in OpenVZ jenkins
on cgroup_inotify00 test.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Duplicate string in irmap_scan_path_add, otherwise it will free before
parsing next configuration input.
[ avagin: handle errors of xstrdup ]
Signed-off-by: Liu Hua <weldonliu@tencent.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Commit fc683cb01 ("compel: shstk: save CET state when CPU supports it")
started using PTRACE_ARCH_PRCTL to query shadow stack status. While
PTRACE_ARCH_PRCTL has existed in the kernel for a long time, it was only
added to glibc in version 2.27. Amazon Linux 2 (AL2) has glibc 2.26,
which does not have this definition. As a result, build on AL2 fails
with the below error:
compel/arch/x86/src/lib/infect.c: In function ‘get_task_xsave’:
compel/arch/x86/src/lib/infect.c:276:14: error: ‘PTRACE_ARCH_PRCTL’ undeclared (first use in this function)
276 | if (ptrace(PTRACE_ARCH_PRCTL, pid, (unsigned long)&features, ARCH_SHSTK_STATUS)) {
| ^~~~~~~~~~~~~~~~~
While the definition is present on the system via the kernel headers (in
asm/ptrace-abi.h) which can be reached by including linux/ptrace.h, the
comment in compel/include/uapi/ptrace.h says:
We'd want to include both sys/ptrace.h and linux/ptrace.h, hoping
that most definitions come from either one or another. Alas, on
Alpine/musl both files declare struct ptrace_peeksiginfo_args, so
there is no way they can be used together. Let's rely on libc one.
Since including linux/ptrace.h is not an option, define
PTRACE_ARCH_PRCTL if it doesn't already exist. An interesting point to
note is that in sys/ptrace.h, PTRACE_ARCH_PRCTL is an enum value so the
preprocessor doesn't know about it. PT_ARCH_PRCTL is the preprocessor
symbol that matches the value of PTRACE_ARCH_PRCTL. So look for
PT_ARCH_PRCTL to decide if PTRACE_ARCH_PRCTL is available or not.
Another interesting point to note is that AL2 ships with GCC 7 by
default, which does not support the -mshstk option, causing other build
failures. Luckily, it also ships GCC 10 which does have the option.
Using GCC 10 lets the build succeed.
Fixes: fc683cb01 ("compel: shstk: save CET state when CPU supports it")
Signed-off-by: Pratyush Yadav <ptyadav@amazon.de>
Adding support for the NVIDIA cuda-checkpoint utility, requires the use of an
r555 or higher driver along with the cuda-checkpoint binary.
Signed-off-by: Jesus Ramos <jeramos@nvidia.com>
PAUSE_DEVICES is called before a process is frozen and is used by the CUDA
plugin to place the process in a state that's ready to be checkpointed and
quiesce any pending work
CHECKPOINT_DEVICES is called after all processes in the tree have been frozen
and PAUSE'd and performs the actual checkpointing operation for CUDA
applications
Signed-off-by: Jesus Ramos <jeramos@nvidia.com>
Restore rseq_cs state before calling RESUME_DEVICES_LATE as the CUDA plugin will
temporarily unfreeze a thread during the plugin hook to assist with device
restore
Run the plugin finalizer later in the dump sequence since the finalizer is used
by the CUDA plugin to handle some process cleanup
Signed-off-by: Jesus Ramos <jeramos@nvidia.com>
Move PYTHON_EXTERNALLY_MANAGED and PIP_BREAK_SYSTEM_PACKAGES
into Makefile.install to avoid code duplication. In addition, add
PIPFLAGS variable to enable specifying pip options during installation.
This is particularly useful for packaging, where it is common for `pip install`
to run in an environment with pre-installed dependencies and without internet
access. In such environment, we need to specify the following options:
--no-build-isolation --no-index --no-deps
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Adds a exit_signal static method to criu_cli, criu_config and criu_rpc
used to detect a crash.
Fixes: #350
Signed-off-by: Bhavik Sachdev <b.sachdev1904@gmail.com>
This commit adds a `--preload-libfault` option to ZDTM's run command.
This option runs CRIU with LD_PRELOAD to intercept libc functions
such as pread(). This method allows to simulate special cases,
for example, when a successful call to pread() transfers fewer
bytes than requested.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
It is possible for pread() to return fewer number of bytes than
requested. In such case, we need to repeat the read operation
with appropriate offset.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The unix_conf_op function reads the size of the sysctl entry array
twice. gcc thinks that it can lead to a time-of-check to time-of-use
(TOCTOU) race condition if the array size changes between the two reads.
Fixes#2398
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The rawhide tests runs in a container. Containers always have SELinux
disabled from the inside. Somehow /sys/fs/selinux is now mounted. We
used the existence of that directory if SELinux is available. This seems
to be no longer true.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
A fault-injection test was introduced in commit [1] and later removed in
commit [2]. This patch removes the obsolete Makefile target.
[1] b95407e264
test: check, that parasite can rollback itself (v2)
[2] 2cb4532e26
tests: remove zdtm.sh (v2)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Replace sprintf() with snprintf() and specify maximum length of
characters to avoid potential overflow.
Reported-by: GitHub CodeQL (https://codeql.github.com/)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Currently there are no socket option test cases for TCP_CORK and
TCP_NODELAY, this commit adds related test cases.
The socket option test cases for TCP_KEEPCNT, TCP_KEEPIDLE, and
TCP_KEEPINTVL already exist in socket-tcp_keepalive.c, so they are
not included in this test case.
Signed-off-by: Juntong Deng <juntong.deng@outlook.com>
Currently some TCP socket option information is stored in SkOptsEntry,
which is a little confusing.
SkOptsEntry should only contain socket options that are common to
all sockets.
In this commit move the TCP-specific socket options from SkOptsEntry
to TcpOptsEntry.
Signed-off-by: Juntong Deng <juntong.deng@outlook.com>
Currently some of the TCP socket option information is stored in the
TcpStreamEntry, but the information in the TcpStreamEntry is only
restored after the TCP socket has established connection, which
results in these TCP socket options not being restored for
unconnected TCP sockets.
In this commit move the TCP socket options from TcpStreamEntry to
TcpOptsEntry and add dump_tcp_opts() and restore_tcp_opts() for TCP
socket options dump and restore.
Signed-off-by: Juntong Deng <juntong.deng@outlook.com>
On some systems, nft binary might not be installed, or some kernel
options might be unconfigured, resulting in something like this:
sudo unshare -n nft create table inet CRIU
Error: Could not process rule: Operation not supported
create table inet CRIU
^^^^^^^^^^^^^^^^^^^^^^^
This is similar to what kerndat_has_nftables_concat() does, and if the
outcome is the same, it returns an error to kerndat_init(), and an error
from kerndat_init() is considered fatal.
Let's relax the check, returning mere "feature not working" instead of
a fatal error.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1) In dump_tcp_conn_state, if return from libsoccr_save is >=0, we check
that sizeof(struct libsoccr_sk_data) returned from libsoccr_save is
equal to sizeof(struct libsoccr_sk_data) we see in dump_tcp_conn_state
(probably to check if we use the right library version). And if sizes
are different we go to err_r, which just returns ret, which can
teoretically be 0 (if size in library is zero) and that would lead
dump_one_tcp treat this as success though it is obvious error.
2) In case of dump_opt or open_image fails we don't explicitly set ret
and rely that sizeof(struct libsoccr_sk_data) previously set to ret is
not 0, I don't really like it, it makes reading code too complex.
3) We have a lot of err_* labels which do exactly the same thing, there
is no point in having all of them, also it is better to choose the name
of the label based on what it really does.
So let's refactor error handling to avoid these inconsistencies.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
During restore, CRIU prints "Enqueue page-read" messages for
each page-read request [1]. However, this message does not
provide useful information, increases performance overhead
during restore and the size of log file.
$ ./zdtm.py run -t zdtm/static/maps06 -f h -k always
$ grep 'Enqueue page-read' dump/zdtm/static/maps06/56/1/restore.log | wc -l
20493
This commit replaces these log messages with a single message
that shows the number of enqueued page-read requests.
$ grep 'enqueued' dump/zdtm/static/maps06/56/1/restore.log
(00.061449) 56: nr_enqueued: 20493
[1] 91388fc
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
1. Tell which RPMs or DEBs are required in all cases.
2. Use $(info ...) everywhere.
3. Drop extra nested $(info), instead use (a document) a simpler kludge.
4. Simplify and unify the language, add missing periods.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Currently we have tabs + spaces on the wrapped line but the wrapped part
is not alligned to the opening bracket.
Fixes: bbe26d1b7 ("timer: fix allignment in function definition")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
CircleCI currently prints out the following warning:
This job is using a deprecated image 'ubuntu-2004:202010-01', please update to a newer image
According to https://discuss.circleci.com/t/linux-image-deprecations-and-eol-for-2024/
the recommended image name is: "image: default"
Signed-off-by: Adrian Reber <areber@redhat.com>
This patch extends the sched_policy00 test case to verify that
the SCHED_RESET_ON_FORK flag is restored correctly.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch extends CRIU with support for SCHED_RESET_ON_FORK.
When the SCHED_RESET_ON_FORK flag is set, the following rules
apply for subsequently created children:
- If the calling thread has a scheduling policy of SCHED_FIFO or
SCHED_RR, the policy is reset to SCHED_OTHER in child processes.
- If the calling process has a negative nice value, the nice value
is reset to zero in child processes.
(See 'man 7 sched')
Fixes: #2359
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
A memory interval is a half-open interval, so the condition
when pr->pe->vaddr == vma->e->end should not be interpreted
as an intersection and should cause vma to be marked with VMA_NO_PROT_WRITE.
Fixes: #2364
Signed-off-by: Artem Trushkin <at.120@ya.ru>
The restore of a task with shadow stack enabled adds these steps:
* switch from the default shadow stack to a temporary shadow stack
allocated in the premmaped area
* unmap CRIU mappings; nothing changed here, but it's important that
CRIU mappings can be removed only after switching to a temporary
shadow stack
* create shadow stack VMA with map_shadow_stack()
* restore shadow stack contents with wrss
* switch to "real" shadow stack
* lock shadow stack features
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
There are several gotachs when restoring a task with shadow stack:
* depending on the compiler options, glibc version and glibc tunables
CRIU can run with or without shadow stack.
* shadow stack VMAs are special, they must be created using a dedicated
map_shadow_stack() system call and can be modified only by a special
instruction (wrss) that is only available when shadow stack is
enabled.
* once shadow stack is enabled, it is not writable even with wrss;
writes to shadow stack can be only enabled with ptrace() and only when
shadow stack is enabled in the tracee.
* if the shadow stack is enabled during restore rather than by glibc,
calling retq after arch_prctl() that enables the shadow stack causes
#CP, so the function that enables shadow stack can never return.
Add the infrastructure required to cope with all of those:
* modify the restore code to allow trampoline (arch_shstk_trampoline)
that will enable shadow stack and call restore_task_with_children().
* add call to arch_shstk_unlock() right after the tasks are clone()ed;
this will allow unlocking shadow stack features and making shadow
stack writable.
* add stubs for architectures that do not support shadow stacks
* add implementation of arch_shstk_trampoline() and arch_shstk_unlock()
for x86, but keep it disabled; it will be enabled along with addtion
of the code that will restore shadow stack in the restorer blob
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
Detect if CRIU runs with shadow stack enabled and store the result in
kerndat.
Unlike most kerndat knobs, kdat_has_shstk() does not check for
availability of the shadow stack in the kernel, but rather checks if
criu runs with shadow stack enabled.
This depends on hardware availabilty, kernel and glibc support, compiler
options and glibc tunables, so kdat_has_shstk() must be called every
time CRIU starts and its result cannot be cached.
The result will be used by the code that controls shadow stack
enablement in the next commit.
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
Shadow stacks must be populated using special WRSS instruction. This
instruction is only available when shadow stack is enabled, calling it
with disabled shadow stack causes #UD.
Moreover, shadow stack VMAs cannot be mremap()ed and they must be
created using map_shadow_stack() system call. This requires delaying the
restore of shadow stacks to restorer blob after the CRIU mappings are
cleared.
Introduce rst_shstk_info structure to hold shadow stack parameters
required in the restorer blob and populate this structure in
arch_prepare_shstk() method.
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Shadow stack VMAs cannot be mmap()ed, they must be created using
map_shadow_stack() system call and populated using special wrss
instruction available only when shadow stack is enabled.
Premap them to reserve virtual address space and populate it to have
there contents available for later copying after enabling shadow stack.
Along with the space required by shadow stack VMAs also reserve an extra
page that will be later used as a temporary shadow stack.
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
The shadow stack VMAs require special care because they can only be
created and populated using special system calls.
Add VMA_AREA_SHSTK flag and set it for VMAs that are marked as "ss" in
/proc/pid/smaps
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
When calling sigreturn with CET enabled, the kernel verifies that the
shadow stack has proper address of sa_restorer and a "restore token".
Normally, they pushed to the shadow stack when signal processing is
started.
Since compel calls sigreturn directly, the shadow stack should be
updated to match the kernel expectations for sigreturn invocation.
Add parasite_setup_shstk() that sets up the shadow stack with the
address of __export_parasite_head_start as sa_restorer and with the
required restore token.
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
To support sigreturn with CET enabled parasite must rewind its stack
before calling sigreturn so that shadow stack will be compatible with
actual calling sequence.
In addition, calling sigreturn from top level routine
(__export_parasite_head_start) will significantly simplify the shadow
stack manipulations required to execute sigreturn.
For x86 make fini_sigreturn() return the stack pointer for the signal
frame that will be used by sigreturn and propagate that return value up
to __export_parasite_head_start.
In non-daemon mode parasite_trap_cmd() returns non-positive value
which allows to distinguish daemon and non-daemon mode and properly stop
at int3 in non-daemon mode.
Architectures other than x86 remain unchanged and will still call
sigreturn from fini_sigreturn().
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
All architectures create on-stack structure for floating point save area
in compel_get_task_regs() if the caller passes NULL rather than a valid
pointer.
The only place that calls compel_get_task_regs() with NULL for floating
point save area is parasite_start_daemon() and it is simpler to define
this strucuture on stack of parasite_start_daemon().
The availability of floating point save data is required in
parasite_start_daemon() to detect shadow stack presence early during
parasite infection and will be used in later patches.
Signed-off-by: Mike Rapoport (IBM) <rppt@kernel.org>
Currently we have checkpoint/restore support only of cgroup v2 threaded
controllers. Threads originating in cgroup v1 environments will be
restored to the main thread's cgroup. This change extends the support
for a cgroups v1.
Signed-off-by: Stepan Pieshkin <stepanpieshkin@google.com>
This patch fixes the following lint error:
scripts/criu-ns:219:16: E713 [*] Test for membership should be `not in`
The change in this patch is auto-generated with `ruff --fix`.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Ruff (https://github.com/astral-sh/ruff) is a Python linter
written in Rust, designed to replace Flake8. It is significantly
faster and actively maintained.
In addition to replacing flake8 with ruff, this patch also
creates separate makefile targets for ruff, shellcheck and
codespell, so that they can be tested independently.
RUFF_FLAGS can be used to specify options such as '--fix'.
Example:
make lint
make ruff RUFF_FLAGS=--fix
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch fixes the following flake8 error:
python3 -m flake8 --config=scripts/flake8.cfg lib/pycriu/images/pb2dict.py
lib/pycriu/images/pb2dict.py:361:43: E721 do not compare types, for exact checks use `is` / `is not`, for instance checks use `isinstance()`
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The commit introducing PAGE_IS_SOFT_DIRTY has not been merged
in kernel v6.7.x.
fs/proc/task_mmu: report SOFT_DIRTY bits through the PAGEMAP_SCAN ioctl
e6a9a2cbc1
As a result, CRIU fails with the following error:
Error (criu/pagemap-cache.c:199): pagemap-cache: PAGEMAP_SCAN: Invalid argument'
Error (criu/pagemap-cache.c:225): pagemap-cache: Failed to fill cache for 63 (400000-402000)'
This patch updates check_pagemap() in kerndat to check if PAGE_IS_SOFT_DIRTY is supported.
Fixes: #2334
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Refactor code used to Checkpoint DRM devices. Code is moved
into amdgpu_plugin_drm.c file which hosts various methods to
checkpoint and restore a workload.
Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
Add a new compilation unit to host symbols and methods that will be
needed to C&R DRM devices. Refactor code that indicates support for
C&R and checkpoints KFD and DRM devices
Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu@amd.com>
We already don't treat it as error in the plugin itself, but after
returning -1 from RESUME_DEVICES_LATE hook we print debug message in
criu about failed plugin, let's return 0 instead.
While on it let's replace ret to exit_code.
Fixes: a9cbdad76 ("plugin/amdgpu: Don't print error for "No such process" during resume")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
During the late stages of restore, each process being resumed gets
an ioctl call to KFD_CRIU_OP_RESUME. If the process has no kfd
process info, this call with fail with -ESRCH. This is normal
behaviour, so we shouldn't print an error message for it.
Signed-off-by: David Francis <David.Francis@amd.com>
To improve readability, this patch changes the return type of
iptables_has_criu_jump_target() to a boolean, where 'true' indicates
that iptables has CRIU jump target and 'false' indicates otherwise.
Suggested-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch removes a leftover declaration for log_closedir()
which has been removed in the following commit:
dc80d6f125
log: get rid of LOG_DIR_FD_OFF and opening cwd in log_init()
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Let's use hooked nft chain which actually affects packets.
Fixes: e5f4d8c6f ("test/nfconntrack: use nft or iptables-legacy")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This change adds a new injectable fault (135) to disable PAGEMAP_SCAN and fault
back to read pagemap files.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
PAGEMAP_SCAN is a new ioctl that allows to get page attributes in a more
effeciant way than reading pagemap files.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In commit [1] was introduced a mechanism to auto-generate the files:
sys-exec-tbl*.c, syscalls*.S, syscall-codes*.h, and syscall*.h.
This commit also updated the gitignore rules to ignore auto-generated
files. However, after commit [2], the path for these files has changed
and the patterns specified in gitignore are no longer needed.
[1] bbc2f133 (x86/build: generate syscalls-{64,32}.built-in.o)
[2] 19fadee9 (compel: plugins,std -- Implement syscalls in std plugin)
Reported-by: @felicitia
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The image has a too old version of nettle which does not work with gnutls.
Just upgrade to the latest to make the error go away.
Signed-off-by: Adrian Reber <areber@redhat.com>
Newer versions of 'tail' rely on inotify and after a restore 'tail' is
unhappy with the state of inotify and just stops.
This replaces 'tail' with a minimal shell based test (thanks Andrei).
Signed-off-by: Adrian Reber <areber@redhat.com>
If ioctl(TIOCSLCKTRMIOS) fails with EPERM it means that a CRIU
process lacks of CAP_SYS_ADMIN capability. But we can use
ioctl(TIOCGLCKTRMIOS) to *read* current ->termios_locked
value from the kernel and if it's the same as we already have
we can skip failing ioctl(TIOCSLCKTRMIOS) safely.
Adrian has recently posted [1] a very good patch to allow ioctl(TIOCSLCKTRMIOS)
for processes that have CAP_CHECKPOINT_RESTORE (right now it requires CAP_SYS_ADMIN).
[1] https://lore.kernel.org/all/20231206134340.7093-1-areber@redhat.com/
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
WARNINGS variable should be amended, not redefined.
We still need, e.g., `-Wno-dangling-pointer` to build
criu on loongarch64 with gcc13.
Signed-off-by: Ivan A. Melnikov <iv@altlinux.org>
Checkpoint/restore with version 25.0.0-beta.1 fails
with the following error:
$ docker start --checkpoint=c1 cr
Error response from daemon: failed to create task for container: content digest fdb1054b00a8c07f08574ce52198c5501d1f552b6a5fb46105c688c70a9acb45: not found: unknown
Release notes:
https://github.com/moby/moby/discussions/46816
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
In the compel/arch/arm/plugins/std/syscalls/syscall.def, the syscall number of bind on ARM64 should be 200 instead of 235
Signed-off-by: Sally Kang <snapekang@gmail.com>
Two major highlights of this release:
* LoongArch64 support
* A lot of fixes and improvments form the Google backlog.
The full changelog can be found here: https://criu.org/Download/criu/3.19.
This marks the final release of the 3.x series. The upcoming version
will be 4.0! Additionally, the naming pattern will be changed. Any ideas
are welcome.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Newer versions of pip use an isolated virtual environment when building
Python projects. However, when the source code of CRIT is copied into
the isolated environment, the symlink for `../lib/py` (pycriu) becomes
invalid. As a workaround, we used the `--no-build-isolation` option for
`pip install`. However, this functionality has issues in some versions
of PIP [1, 2]. To fix this problem, this patch adds separate packages
for pycriu and crit, and each package is installed independently.
[1] https://github.com/pypa/pip/pull/8221
[2] https://github.com/pypa/pip/issues/8165#issuecomment-625401463
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
cgroup_ifpriomap test needs net_prio cgroup, which might not be
available. Make the .checkskip script check it.
Signed-off-by: Michał Mirosław <emmir@google.com>
At this point the correct position is already restored, so reading from
the fd results in the position being moved forward by 5 bytes.
Fixes: 9191f8728d ("criu/files-reg.c: add build-id validation functionality")
Signed-off-by: Michal Clapinski <mclapinski@google.com>
Eventpollentry's fields are set only when ret == 3 or ret == 6. The
remaining cases can be grouped together to an error
Signed-off-by: Taemin Ha <taemin.ha@utexas.edu>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
line 131 checks if (ret >= 0). line 133 could be replaced by a simple else statement
Signed-off-by: Taemin Ha <taeminha@cs.utexas.edu>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The condition meant to check fd2 instead of fd1, which is checked in
line 24.
Signed-off-by: Taemin Ha <taeminha@cs.utexas.edu>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The is_native field is a boolean. Therefore, else if() should can be
changed to a simple else{}.
Signed-off-by: Taemin Ha <taeminha@cs.utexas.edu>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This check is redundant as line 201 checks for this condition.
Signed-off-by: Taemin Ha <taeminha@cs.utexas.edu>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
read_ns_sys_file() can return an error, but we are trying to parse a
buffer before checking a return code.
CID 417395 (#3 of 3): String not null terminated (STRING_NULL)
2. string_null: Passing unterminated string buf to strtol, which expects
a null-terminated string.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
GCC's lto source:
> To avoid this problem the compiler must assume that it sees the
> whole program when doing link-time optimization. Strictly
> speaking, the whole program is rarely visible even at link-time.
> Standard system libraries are usually linked dynamically or not
> provided with the link-time information. In GCC, the whole
> program option (@option{-fwhole-program}) asserts that every
> function and variable defined in the current compilation
> unit is static, except for function @code{main} (note: at
> link time, the current unit is the union of all objects compiled
> with LTO). Since some functions and variables need to
> be referenced externally, for example by another DSO or from an
> assembler file, GCC also provides the function and variable
> attribute @code{externally_visible} which can be used to disable
> the effect of @option{-fwhole-program} on a specific symbol.
As far as I read gcc's source, ipa_comdats() will avoid placing symbols
that are either already in a user-defined section or have
externally_visible attribute into new optimized gcc sections.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The "ColumnLimit: 120" is not only allowing lines to be longer than 80
characters but it also forces line wrapping at 120 characters. If total
expression length is more than 120 characters, clang-format will try to
wrap it as close to 120 as it can, it would not even allow to wrap at 80
characters if we really want it. But as we all know 80 characters is
Linux kernel coding style default and as far as our coding style is
based on it it is really strange to prohibit wrapping lines at 80
characters...
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
One memfd can be shared by a few restored files. Only of these files is
restored with a file created with memfd_open. Others are restored by reopening
memfd files via /proc/self/fd/.
It seems unnecessary for restoring memfd memory mappings. We can always use the
origin file.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
amdgpu_plugin.c:930:6: error: variable 'buffer' is used uninitialized whenever 'if' condition is true [-Werror,-Wsometimes-uninitialized]
if (ret) {
^~~
amdgpu_plugin.c:988:8: note: uninitialized use occurs here
xfree(buffer);
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch adds the `libdrm-dev` package to the list of CRIU
dependencies installed in CI to build CRIU with amdgpu plugin.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
It means CRIU has to close it when it is not needed.
It looks more logically correct and matches the behaviour of
the RESTORE_EXT_FILE callback.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Currently most of the times we don't have problems with VVAR segment and
lazy restore because when VDSO is parked there is an munmap call that
calls UFFDIO_UNREGISTER on the destination address.
But we don't want to enable userfaultfd for VDSO and VVAR at the first
place.
Signed-off-by: Vladislav Khmelevsky <och95@yandex.ru>
Currently page_size() returns unsigned int value that is after "bitwise
not" is promoted to unsigned long value e.g. in uffd.c
handle_page_fault. Since the value is unsigned promotion is done with 0
MSB that results in lost of MSB pagefault address bits. So make
page_size to return unsigned long to avoid such situation.
Signed-off-by: Vladislav Khmelevsky <och95@yandex.ru>
When -- after restore -- sockets can't communicate, the test times out
while waiting on recvfrom(). Since the communication is local, send()
works instantaneously - so mark sockets with SOCK_NONBLOCK and report
failure if the message is not received immediately.
Signed-off-by: Michał Mirosław <emmir@google.com>
This fixes a failure to clean up after a failed test, where CRIU didn't start properly.
```
===================== Run zdtm/transition/socket-tcp in h ======================
Start test
./socket-tcp --pidfile=socket-tcp.pid --outfile=socket-tcp.out
Traceback (most recent call last):
File ".../zdtm_py.py", line 1906, in do_run_test
cr(cr_api, t, opts)
File ".../zdtm_py.py", line 1584, in cr
cr_api.dump("dump")
File ".../zdtm_py.py", line 1386, in dump
self.__dump_process = self.__criu_act(action,
File ".../zdtm_py.py", line 1224, in __criu_act
raise test_fail_exc("CRIU %s" % action)
test_fail_exc: CRIU dump
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<embedded module '_launcher'>", line 182, in run_filename_from_loader_as_main
File "<embedded module '_launcher'>", line 34, in _run_code_in_main
File ".../zdtm_py.py", line 2790, in <module>
fork_zdtm()
File ".../zdtm_py.py", line 2782, in fork_zdtm
do_run_test(tinfo[0], tinfo[1], tinfo[2], tinfo[3])
File ".../zdtm_py.py", line 1922, in do_run_test
t.kill()
File ".../zdtm_py.py", line 509, in kill
os.kill(int(self.__pid), sig)
ProcessLookupError: [Errno 3] No such process
```
Signed-off-by: Michał Mirosław <emmir@google.com>
cgroup04 test needs full control over mem and devices cgroup hierarchies.
Make the test's .checkskip script better at detecting if the cgroups are
available for use.
Signed-off-by: Michał Mirosław <emmir@google.com>
Make the errno values reported by cgroup04 always correct and showing
relevant parameters.
Constify constant strings, while at it.
Signed-off-by: Michał Mirosław <emmir@google.com>
At least in Google's VM environment, the kernel taints are unrelated to CRIU
runs. Don't fail tests if taints change, if kernel taints are ignored.
Signed-off-by: Michał Mirosław <emmir@google.com>
They break it with each kernel rebase. More details are here:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1857257
Last time, it was fixed a few month ago and it has been broken again in
5.15.0-1046-azure.
Let's bind-mount the CRIU directory into a test container to make it
independent of a container file system.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The version of CRIU is specified in the Makefile.versions file.
This patch generates '__varion__' value for the pycriu module.
This value can be used by crit to implement `--version`.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Power ISA 3.0 added a new syscall instruction. Kernel 5.9 added
corresponding support.
Add CRIU support to recognize the new instruction and kernel ABI changes
to properly dump and restore threads executing in syscalls. Without this
change threads executing in syscalls using the scv instruction will not
be restored to re-execute the syscall, they will be restored to execute
the following instruction and will return unexpected error codes
(ERESTARTSYS, etc) to user code.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
The amdgpu plugin would create a memory buffer at the size
of the largest VRAM bo (buffer object). On some systems, VRAM
size exceeds RAM size, so the largest bo might be larger than
the available memory.
Add an environment variable KFD_MAX_BUFFER_SIZE, which caps the
size of this buffer. By default, it is set to 0, and has no
effect. When active, any bo larger than its value will be
saved to/restored from file in multiple passes.
Signed-off-by: David Francis <David.Francis@amd.com>
Check membarrier registration both ways:
1. By issuing membarrier commands and checking if they succeed.
2. By issuing MEMBARRIER_CMD_GET_REGISTRATIONS.
The first way is needed for older kernels. The second way is needed to test
MEMBARRIER_CMD_GLOBAL_EXPEDITED.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
MEMBARRIER_CMD_GET_REGISTRATIONS can tell us whether or not the process used
MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED unlike the old probing method.
Falls back to the old method when MEMBARRIER_CMD_GET_REGISTRATIONS is
unavailable.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
There are multiple cases where good human readable code block is
converted to an unreadable mess by clang-format, so we don't want to
rely on clang-format completely. Also there is no way, as far as I can
see, to make clang-format only fix what we want it to fix without
breaking something.
So let's just display hints inline where clang-format is unhappy. When
reviewer sees such a warning it's a good sign that something is broken
in coding-style around this warning.
We add special script which parses diff generated by indent and
generates warning for each hunk.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is highlight that code readability is the real goal of all the
coding-style rules. We should not do coding-style just for coding-style,
e.g. when clang-format suggests crazy formating we should not follow it
if we feel it is bad.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Ctags is mentioned in the beginning of the "Edit the source code" which
is really confusing: Do you need ctags to edit CRIU code? - No. It is
just one helpful tool to browse the code, and we do not want to enforce
it. So, what is it doing in contribution guide? People who really need
it should be able to find it in Makefile or just write oneliner of their
own to collect tags...
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If there is only a single RW opened fd for a memfd, it can be used
to pass it to execveat() with AT_EMPTY_PATH to have its contents
executed. This currently works only for the original fd from
memfd_create(). For now we ignore processes that reopen the memfd's
rw and expect a particular executability trait of it. (Note: for
security purposes recent kernels have SEAL_EXEC to make memfds
non-executable.)
Signed-off-by: Michał Mirosław <emmir@google.com>
Plug a fd leak when returning error from check_pagemap().
(Cosmetic, as the process will exit soon anyway.)
Signed-off-by: Michał Mirosław <emmir@google.com>
This commit is introducing a test for the action-script functionality
of CRIU to verify that pre-dump, post-dump, pre-restore, pre-resume,
post-restore, post-resume hooks are executed during dump/restore.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Fix test of whether the kernel exposes page frame numbers to cope with the
possibility that the top of the stack is swapped out, which was happening
in about one 1 out of 3 million runs. This lead to a later failure when
trying to read the PFN of the zero page, after which criu would exit with
no error message.
Original-From: Ambrose Feinstein <ambrose@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
There is only one user of memfd_open() outside of memfd.c: open_filemap().
It is restoring a file-backed mapping and doesn't need nor expect to
update F_SETOWN nor the fd's position. Check the inherited_fd() handling
in the callers to simplify the code.
Signed-off-by: Michał Mirosław <emmir@google.com>
The 288d6a61e2 change broke all the syscall numbers.
Reported-by: Michał Mirosław <emmir@google.com>
Fixes: (288d6a61e2 "loongarch64: reformat syscall_64.tbl for 8-wide tabs")
Signed-off-by: Andrei Vagin <avagin@gmail.com>
While each preadv() is followed by a fallocate() that removes the data
range from image files on tmpfs, temporarily (between preadv() and
fallocate()) the same data is in two places; this increases the memory
overhead of restore operation by the size of a single preadv.
Uncapped preadv() would read up to 2 GiB of data, thus we limit that to
a smaller block size (128 MiB).
Based-on-work-by: Paweł Stradomski <pstradomski@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
Note: Silently drops MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED as it's
not currently detectable. This is still better than silently dropping
all membarrier() registrations.
Signed-off-by: Michał Mirosław <emmir@google.com>
The VMA_AREA_MEMFD constant was introduced with commit
29a1a88bce
memfd: add memory mapping support
This patch extends the status map used in CRIT and coredump with the
value of this constant to recognize it.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This change fixes the issue:
```
The following packages have unmet dependencies:
docker-ce : Depends: containerd.io (>= 1.6.4)
E: Unable to correct problems, you have held broken packages.
```
Signed-off-by: Andrei Vagin <avagin@google.com>
The log prefix "amdgpu_plugin:" is defined with `LOG_PREFIX` in
`amdgpu_plugin.c`. However, the prefix is also included in each
log message. As a result it appears duplicated in the log messages:
(00.044324) amdgpu_plugin: amdgpu_plugin: devices:1 bos:58 objects:148 priv_data:45696
(00.045376) amdgpu_plugin: amdgpu_plugin: Thread[0x5589] started
(00.167172) amdgpu_plugin: amdgpu_plugin: img_path = amdgpu-kfd-62.img
(00.083739) amdgpu_plugin: amdgpu_plugin : amdgpu_plugin_dump_file() called for fd = 235
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Make the scan use the order of paths that came from the user.
Fixes: 4f2e4ab3be ("irmap: add --irmap-scan-path option"; 2015-09-16)
Signed-off-by: Michał Mirosław <emmir@google.com>
Move tcp_cork() and tcp_nodelay() to the only user: page-xfer.c. While
at it, fix error messages (as they do not refer to restoring the sockopt
values) and demote them as they are not fatal to the page transfer.
Signed-off-by: Michał Mirosław <emmir@google.com>
In criu/apparmor.c: write_aa_policy(), the arg path is passed as a char
pointer. The original code used sizeof(path) to get the size of it,
which is incorrect as it always return the size of the char pointer
(typically 8 or 4), not the actual capacity of the char array.
Given that this function is only invoked with path declared as `char
path[PATH_MAX]`, replacing sizeof(path) with PATH_MAX should correctly
represent the maximum size of it.
Fixes: 8723e3f ("check: add a feature test for apparmor_stacking")
Signed-off-by: Haorong Lu <ancientmodern4@gmail.com>
memfd is created by default with +x permissions set. This can be changed
by a process using fchmod() and expected to prevent using this fd for
exec(). Migrate the permissions.
Signed-off-by: Michał Mirosław <emmir@google.com>
Include the file descriptor and error code in the debug message to make
it more useful.
Fixes: e7ba90955c (2016-03-14 "cr-check: Inspect errno on syscall failures")
Signed-off-by: Michał Mirosław <emmir@google.com>
prctl(NO_NEW_PRIVS) when set prevents child processes gaining
capabilities not in permitted set. In this case, inability to
clear capability from BSET that is not in the permitted set is
harmless.
Signed-off-by: Michał Mirosław <emmir@google.com>
When restoring on a kernel that has different number of supported
capabilities than checkpoint one, check that the extra caps are unset.
There are two directions to consider:
1) dump.cap_last_cap > restore.cap_last_cap
- restoring might reduce the processes' capabilities if restored
kernel doesn't support checkpointed caps. Warn.
2) dump.cap_last_cap < restore.cap_last_cap
- restoring will fill the extra caps with zeroes. No changes.
Note: `last_cap` might change without affecting `n_words`.
Signed-off-by: Michał Mirosław <emmir@google.com>
Skip calling setgroups() when the list of auxiliary groups already has
the values we want. This allows restoring into an unprivileged user
namespace where setgroups() is disabled.
From: Ambrose Feinstein <ambrose@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
When CRIU is run with the task's credentials on restore, don't set uids
and gids. This avoids the need to modify the SECURE_NO_SETUID_FIXUP flag
which requires CAP_SETPCAP.
From: Andy Tucker <agtucker@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
Note: This removes the difference in calling convention of
restore_file_perms() returning -errno that was the only call that did
this in the caller.
From: Radosław Burny <rburny@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
Add generic wrappers for fchown() and fchmod() that skip the calls if
no changes are needed. This will allow to unify places where we can
avoid errors when no-op requests are not permitted.
Signed-off-by: Michał Mirosław <emmir@google.com>
NR_fstat is a deprecated syscall, some
modern architectures such as riscv and
loongarch64 no longer support this syscall.
It is usually replaced by NR_statx.
NR_statx is supported since linux 4.10.
Signed-off-by: znley <shanjiantao@loongson.cn>
Fixes: #2222
Fixes: f1c8d38 ("kerndat: check if setsockopt IPV6_FREEBIND is supported")
Signed-off-by: Yan Evzman <yevzman@gmail.com>
Signed-off-by: Andrei Vagin <avagin@google.com>
These errors originate from the filesystem scanning in irmap.c and are mostly
benign. Nevertheless, if they do result in a failed irmap lookup, that failed
lookup is more interesting from an application perspective.
Signed-off-by: Michał Mirosław <emmir@google.com>
Make logs about inaccessible mounts warnings, as the failures are
normally harmless (e.g. failure to read /dev/cgroup) and don't
make the CRIU run fail. (If it happens that the fsnotify can't
find a file, then to debug, full CRIU logs will be necessary anyway.)
Signed-off-by: Michał Mirosław <emmir@google.com>
Errors in early restore.log for status=1 from a subprocess are confusing,
esp. that they don't show what command failed. Since the result is
either ignored or logged anyway, mark the calls as "can fail".
Signed-off-by: Michał Mirosław <emmir@google.com>
This makes the error to mount cgroup hierarchy a bit less noisy:
Error (criu/cgroup.c:623): cg: Unable to mount cgroup2 : Invalid argument'
Instead of
Error (criu/cgroup.c:623): cg: Unable to mount cgroup2 : Invalid argument'
Error (criu/cgroup.c:715): cg: failed walking /proc/self/fd/-1/zdtmtst for empty cgroups: No such file or directory'
Signed-off-by: Michał Mirosław <emmir@google.com>
This patch removes the code for Python 2 compatibility introduced
with commit e65c7b5 (zdtm: Replace imp module with importlib).
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch is replacing the set_blocking() function with
os.set_blocking(). This function was introduced for compatibility with
Python 2 in commit 8094df8di (criu-ns: Add tests for criu-ns script).
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit removes the checks for the Python 2 binary in the makefile
and makes sure that ZDTM tests always use python3. Since support for
Python 2 has been dropped, these checks are no longer needed.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This commit removes the dependency on the __future__ module, which was
used to enable Python 3 features in Python 2 code. With support for
Python 2 being dropped, it is no longer necessary to maintain backward
compatibility.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When building with pip version 20.0.2 or older, the pip install
command creates a temporary directory and copies all files from
./crit. This results in the following error message:
ModuleNotFoundError: No module named 'pycriu'
This error appears because the symlink 'pycriu' uses a relative path
that becomes invalid '../lib/py/'.
The '--no-build-isolation' option for pip install is needed to enable
the use of pre-installed dependencies (e.g., protobuf) during build.
The '--ignore-installed' option for pip is needed to avoid an error when
crit is already installed. For example, crit is installed in the GitHub
CI environment as part of the criu OBS package as a dependency for
podman.
Distributions such as Arch Linux have adopted an externally managed
python installation in compliance with PEP 668 [1] that prevents pip
from breaking the system by either installing packages to the system or
locally in the home folder. The '--break-system-packages' [2] option
allows pip to modify an externally managed Python installation.
[1] https://peps.python.org/pep-0668/
[2] https://pip.pypa.io/en/stable/cli/pip_uninstall/
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch reverts changes introduced with the following commits:
4feb07020d
crit: enable python2 or python3 based crit
b78c4e071a
test: fix crit test and extend it
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch reverts changes introduced for Python 2 compatibility
in commits:
1c866db (Add new files for running criu-coredump via python 2 or 3)
3180d35 (Add support for python3 in criu-coredump).
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
We have disabled CentOS 7 tests in CI. This patch reverts the
changes introduced in the following commit:
24bc083653
ci: disable some tests on CentOS 7
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Instead of opening the image directly, the commit refactors the
asciinema image embedded link to redirect users to the corresponding
video.
Signed-off-by: Abhishek Guleri <abhishekguleri24@gmail.com>
With the parasite socket clash now guaranteed not to happen,
the comment becomes obsolete. netns is steel needed though, so
update the comment to point at the requirement.
Change-Id: I3cfb253cd5c53b91b955fcb001530b4aee5129f4
Signed-off-by: Michał Mirosław <emmir@google.com>
Instead of relying on chance of CLOCK_MONOTONIC reading being unique,
use pid namespace ID that combined with the process ID will make it
unique on the machine level.
If pidns is not enabled on a kernel we'll get ENOENT, but then CRIU's
pid will already be unique. If there is some other error, log it but
continue, as the socket clash (if it happens) will result in a failed
run anyway.
Fixes: 45e048d77a (2022-03-31 "criu: generate unique socket names")
Fixes: 408a7d82d6 (2022-02-12 "util: add an unique ID of the current criu run")
Change-Id: I111c006e1b5b1db8932232684c976a84f4256e49
Signed-off-by: Michał Mirosław <emmir@google.com>
If not dumping netns nor connections, nsid support is not used. Don't
fail the run as if the support is needed, the dumping process will fail
later.
Change-Id: I39a086756f6d520c73bb6b21eaf6d9fb49a18879
Signed-off-by: Michał Mirosław <emmir@google.com>
kerndat_nsid() is not used outside kerndat.c. Make it static.
Change-Id: I52e518ecb7c627cc1866e373411b2be3f71a2c9d
Signed-off-by: Michał Mirosław <emmir@google.com>
If the error is ignored it is not important enough - make it a warning
instead.
From: Mian Luo <mianl@google.com>
Change-Id: If2641c3d4e0a4d57fdf04e4570c49be55f526535
Signed-off-by: Michał Mirosław <emmir@google.com>
Google's RPC client process is in a different pidns and has more privileges --
CRIU can't open its /proc/<pid>/fd/<fd>. For images_dir_fd to be useful here
it would need to refer to a passed or CRIU's fd.
From: Michał Cłapiński <mclapinski@google.com>
Change-Id: Icbfb5af6844b21939a15f6fbb5b02264c12341b1
Signed-off-by: Michał Mirosław <emmir@google.com>
New 'query-ext-files' action for `criu dump` is sent after
freezing the process tree. This allows to defer gathering
the external file list when the process tree is in a stable
state and avoids race with the process creating and deleting
files.
Change-Id: Iae32149dc3992dea086f513ada52cf6863beaa1f
Signed-off-by: Michał Mirosław <emmir@google.com>
Container runtimes commonly use CRIU with RPC. However, this prevents
the use of action-scripts set in a CRIU configuration file due to the
explicit scripts mode introduced with the following commit:
ac78f13bdf
actions: Introduce explicit scripts mode
This patch enables container checkpoint/restore with action-scripts
specified via configuration file.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
nla_get_s32() was added to libnl 3.2.7 in 2015. Remove CRIU's definition
as it breaks build when statically linking the binary.
From: Uros Prestor <urosp@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
When trying to build CRIU with libbsd enabled the compilation fails due
to duplicate definition of __aligned macro. Other such definitions are
already wrapped with #ifndef make __aligned definition consistent and
make it easier in the future to use the libbsd features if needed.
Signed-off-by: Michał Mirosław <emmir@google.com>
$LDFLAGS can contain `-Ldir`s that are required by '-lib's in $LIBS.
Reverse the order so that `-L` options make effect.
Signed-off-by: Michał Mirosław <emmir@google.com>
`make` without `-s` option will normally show the commands executed. In
the case of detecting build environment features current makefile will
cause detected features to be seen as 'echo #define' commands, but not
detected ones will be silent. Change it so that all tried features can
be seen (outside of make's silent mode) regardless of detection result.
Signed-off-by: Michał Mirosław <emmir@google.com>
The test for HAS_MEMFD is empty and noit used. Remove it.
Fixes: 5ee1ac1f28 ("criu: remove FEATURE_TEST_MEMFD")
Change-Id: I43b8f0cfd50ce9bdf93dafb647377318df1deae8
Signed-off-by: Michał Mirosław <emmir@google.com>
During dump, CRIU stores the structs representing sockets in a statically sized
hashmap of size 32. We have some (admittedly crazy) tasks that use tens of
thousands of sockets, and seem to spend most of the dump time iterating over
the linked lists of the map.
16K is chosen arbitrarily, so that it reduces the lengths of the chains to few
elements on average, while not introducing significant memory overhead.
From: Radosław Burny <rburny@google.com>
Signed-off-by: Michał Mirosław <emmir@google.com>
The fail() macro provides a new line character at the end of the
message. This patch fixes the following lint check that currently
fails in CI:
$ git --no-pager grep -E '^\s*\<(pr_perror|fail)\>.*\\n"'
test/zdtm/static/thp_disable.c: fail("prctl(GET_THP_DISABLE) returned unexpected value: %d != 1\n", ret);
test/zdtm/static/thp_disable.c: fail("Flags changed %lx -> %lx\n", orig_flags, new_flags);
test/zdtm/static/thp_disable.c: fail("Madvs changed %lx -> %lx\n", orig_madv, new_madv);
test/zdtm/static/thp_disable.c: fail("post-migration prctl(GET_THP_DISABLE) returned unexpected value: %d != 1\n", ret);
test/zdtm/static/thp_disable.c: fail("Flags changed %lx -> %lx\n", orig_flags, new_flags);
test/zdtm/static/thp_disable.c: fail("Madvs changed %lx -> %lx\n", orig_madv, new_madv);
Fixes: #2193
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Make it possible to skip network lock to enable uses that break connections
anyway to work without iptables/nftables being present.
Signed-off-by: Michał Mirosław <emmir@google.com>
Make it clear that the option numbers are indexes not the option
identifiers ("names"). Also show the value change that prompted test
failure.
Signed-off-by: Michał Mirosław <emmir@google.com>
We don't want test framework to change its behaviour on whether we
run a single or multiple tests in a run. When we shard the test suite
it can result in some shards having a single test to run and
unexpectedly change the test output format.
Signed-off-by: Michał Mirosław <emmir@google.com>
This commit revises the error handling in the fdspy test. Previously,
a failure case could have been incorrectly reported as successful because
of a specific check `pass != 0`, leading to potential false positives
when `check_pipe_ends()` returned `-1` due to a read/write pipe error.
To improve this, we've adjusted the error handling to return `0` in case
of any error. As such, the final success condition remains unchanged. This
approach will help accurately differentiate between successful and failed
cases, ensuring the output "All OK" is printed for success, and "Something
went WRONG" for any failure.
Fixes: 5364ca3 ("compel/test: Fix warn_unused_result")
Signed-off-by: Haorong Lu <ancientmodern4@gmail.com>
Apparently Skylake uses init-optimization when saving FPU state, and ptrace()
returns XSTATE_BV[0] = 0 meaning FPU was not used by a task (in init state).
Since CRIU restore uses sigreturn to restore registers, FPU state is always
restored. Fill the state with default values on dump to make restore happy.
Signed-off-by: Michał Mirosław <emmir@google.com>
The original commit added saving THP_DISABLED flag value, but missed
restoring it. There is restoring code, but used only when --lazy_pages
mode is enabled. Restore the prctl flag always. While at it, rename the
`has_thp_enabled` -> `!thp_disabled` for consistency.
Fixes: bbbd597b41 (2017-06-28 "mem: add dump state of THP_DISABLED prctl")
Signed-off-by: Michał Mirosław <emmir@google.com>
Linux 4.15 doesn't like empty string for cgroup2 mount options.
Pass NULL then to satisfy the kernel check. Log the options for
easier debugging.
Signed-off-by: Michał Mirosław <emmir@google.com>
4.15-based kernels don't allow F_*SEAL for memfds created with MFD_HUGETLB.
Since seals are not possible in this case, fake F_GETSEALS result as if it
was queried for a non-sealing-enabled memfd.
Signed-off-by: Michał Mirosław <emmir@google.com>
This does cgroup namespace creation separately from joining task
cgroups. This makes the code more logical, because creating cgroup
namespace also involves joining cgroups but these cgroups can be
different to task's cgroups as they are cgroup namespace roots
(cgns_prefix), and mixing all of them together may lead to
misunderstanding.
Another positive thing is that we consolidate !item->parent checks in
one place in restore_task_with_children.
Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is a patch proposed by Thomas here:
https://lore.kernel.org/all/87ilczc7d9.ffs@tglx/
It removes (created id > desired id) "sanity" check and adds proper
checking that ids start at zero and increment by one each time when we
create/delete a posix timer.
First purpose of it is to fix infinite looping in create_posix_timers on
old pre 3.11 kernels.
Second purpose is to allow kernel interface of creating posix timers
with desired id change from iterating with predictable next id to just
setting next id directly. And at the same time removing predictable next
id so that criu with this patch would not get to infinite loop in
create_posix_timers if this happens.
Thanks a lot to Thomas!
Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
CentOS 7 CI environment uses Python 2. To execute criu-ns
script in CentOS 7 changing the current shebang line to
python is required.
This reverse the changes made in a15a63fce0
Signed-off-by: Dhanuka Warusadura <csx@tuta.io>
These changes fix the `ImportError: No module named pathlib`
error when executing criu-ns tests located at criu/test/others/criu-ns
Signed-off-by: Dhanuka Warusadura <csx@tuta.io>
These changes remove and update the changes introduced in
7177938e60 in favor of the
Python version in CI.
os.waitstatus_to_exitcode() function appeared in Python 3.9
Related to: #1909
Signed-off-by: Dhanuka Warusadura <csx@tuta.io>
--criu-binary argument provides a way to supply the CRIU binary
location to run_criu().
Related to: #1909
Signed-off-by: Dhanuka Warusadura <csx@tuta.io>
By default, the file name 'amdgpu_plugin.txt' is used also as the name
for the corresponding man page (`man amdgpu_plugin`). However, when
this man page is installed system-wide it would be more appropriate
to have a prefix 'criu-' (e.g., `man criu-amdgpu-plugin`).
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Using the fact that we know criu_pid and criu is a parent of restored
process we can create pidfile with pid on caller pidns level.
We need to move mount namespace creation to child so that criu-ns can
see caller pidns proc.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Newer Intel CPUs (Sapphire Rapids) have a much larger xsave area than
before. Looking at older CPUs I see 2440 bytes.
# cpuid -1 -l 0xd -s 0
...
bytes required by XSAVE/XRSTOR area = 0x00000988 (2440)
On newer CPUs (Sapphire Rapids) it grows to 11008 bytes.
# cpuid -1 -l 0xd -s 0
...
bytes required by XSAVE/XRSTOR area = 0x00002b00 (11008)
This increase the xsave area from one page to four pages.
Without this patch the fpu03 test fails, with this patch it works again.
Signed-off-by: Adrian Reber <areber@redhat.com>
The pipe_size type is unsigned int, when the fcntl call fails and
return -1, it will cause a negative rollover problem.
Signed-off-by: zhoujie <zhoujie133@huawei.com>
The TOS(type of service) field in the ip header allows you specify the
priority of the socket data.
Signed-off-by: Suraj Shirvankar <surajshirvankar@gmail.com>
The highlight feature of this release is the ability to use CRIU for
non-root users. Adrian Reber implemented the kernel part and created the
initial version of CRIU changes. Then Younes Manton joined the effort
and pushed it to the finish line.
The full change log is here: https://criu.org/Download/criu/3.18
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We do kerndat_has_nspid in kerndat_init already and save result to
kerndat cache, we don't need to recheck it each time.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previously when tv_sec>=100, the line would look like this:
(269.189615 Error [...]
Now the last char is overwritten with ')'.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
In parse_pid_status there are 13 places where we do done++, so when
"done" is 13 it means that we have matched each of those 13 places and
we are ready to stop. In next lines we are not going to find anything.
So the right condition for the while loop is (done < 13).
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
During the restore process, netlink fd uses the flags in the
NetlinkSkEntry structure to restore the file state, but during
the dump process, the flags values is not saved to the structure.
Signed-off-by: zhoujie <zhoujie133@huawei.com>
Signed-off-by: hejingxian <hejingxian@huawei.com>
Previously fixup was done before threads' registers were dumped so it
didn't actually work. This commit splits rseq fixup into thread leader
fixup and other threads fixup and applies them after the entities are
seized.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
Kernel shouldn't clean up rseq_cs inside a critical section.
If rseq_cs has been cleaned up, it means there is a bug in migration.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
This patch adds concurrency groups to the CI workflows to automatically
cancel any in-progress workflows when a pull request has been updated.
A `concurrency` group allows to ensure that a single job or workflow
will run at a time. For example, when a pull request is updated with
a force-push, the GiHub CI workflows currently in-progress will be
automatically cancelled, and the CI would run only with the updated
commits.
https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#concurrency
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
- use exit_code instead of returning ret
- replace -errno return with -1
- move fallback to if (!kdat.sk_unix_file)
- fix readlinkat error checking (ret < 0 && ret >= PATH_MAX) by using
read_fd_link helper
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
As we now don't have any calls to free in this function we can replace
all lables with explicit returns.
While on it: Replace useless -errno and 1 returns with -1 as from the
very first implementation of unix_resolve_name (it changed name to _old
later) in [1] any non-zero return was treated as error.
6d785e6cd ("unix: resolve a socket file when a socket descriptor is
available") [1]
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
It is strange to free a pointer which is already in unix_sk_desc, either
on error path or on skip as we leave freed pointer in desc and it can
probably be used after free later and lead to some corruption. So I
would prefer not to free it as we don't have full controll over it here.
Fixes: 6d785e6cd ("unix: resolve a socket file when a socket descriptor is available")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Fix cwd freeing on error path in get_cwd_check_perm and
on non-error-path in unix_fill_sock_name.
v2: use cleanup_free attribute in unix_fill_sock_name
Signed-off-by: Yuriy Vasiliev <yuriy.vasiliev@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
First, let's move lookup_create_item-s to the end so that on pgid
replacement we don't have false positive pstree_pid_by_virt check
founding item created by sid replacement. (note: we need those
lookup_create_item-s for the sake of free pid selection mechanism)
Second, let's add checks for sid/pgid in images intersecting with
current_sid/pgid, as this would also bring problems on restore.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In Virtuozzo tests we have seen uninformative errors:
(26.575039) 151187 fdinfo 6: pos: 0 flags: 2/0
(26.575076) sockets: Searching for socket 0x346d1 family 1
(666.230281 ----------------------------------------
(666.230586 Error (criu/cr-dump.c:1850): Dump files (pid: 151187) failed
with -1
So let's add some error messages to this stack.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
With this macro we can easily declare struct mntns_zdtm variables with
all lists properly initiallized. Let's use it in mount_complex_sharing
as without it we can have segfault on error path when accessing
uninitialized list pointers.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Currently we only allow external fuse mount itself, let's allow
bindmount for it too. Other mount code is ready for this change and will
be able to bindmount it from corresponding external mount.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
When installing packages within Archlinux container, pacman fails with
the following errors:
(3/7) Creating temporary files...
/usr/lib/tmpfiles.d/journal-nocow.conf:26: Failed to replace specifiers in '/var/log/journal/%m': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:23: Failed to replace specifiers in '/run/log/journal/%m': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:25: Failed to replace specifiers in '/run/log/journal/%m': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:26: Failed to replace specifiers in '/run/log/journal/%m/*.journal*': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:29: Failed to replace specifiers in '/var/log/journal/%m': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:30: Failed to replace specifiers in '/var/log/journal/%m/system.journal': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:32: Failed to replace specifiers in '/var/log/journal/%m': No such file or directory
/usr/lib/tmpfiles.d/systemd.conf:33: Failed to replace specifiers in '/var/log/journal/%m/system.journal': No such file or directory
To solve this problem we need to initialize the machine ID.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch optimizes shell code as reading a single file as input using a 'cat' command to a program.
It is considered to be a Useless Use of Cat (UUOC).
It's more efficient to simply use redirection.
However, in some cases, even using the redirection operator '<' seems unnecessary.
Signed-off-by: KKrypt <sankalpacharya1211@gmail.com>
When we collect external mount namespace we don't want to dump mounts in
it, so lets remove this flag. This way we can e.g. use for_dump in
->parse() callbacks to separate in-container mounts from others.
This only affects rare case of `--ext-mount-map auto` but to be
absolutely correct let's fix it anyway.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The new field cg_set is currently marked as required which causes backward
compatibility problem when using newer CRIU version to restore dumped image
from older version. This commit makes this field optional and reworks the
logic to fallback to use cg_set from task_core when it is not in
thread_core.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
The new field is_threaded is currently marked as required which causes
backward compatibility problem when using newer CRIU version to restore
dumped image from older version. This commit makes this field optional and
reworks the logic the skip fixing up threaded cgroup controllers if there
is no information in dumped image.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
The patch is similar to what has been done in linux kernel, as this
warning effectively prevents us from adding list elements to local list
head. See 49beadbd47
Else we have:
CC criu/mount.o
In file included from criu/include/cr_options.h:7,
from criu/mount.c:13:
In function '__list_add',
inlined from 'list_add' at include/common/list.h:41:2,
inlined from 'mnt_tree_for_each' at criu/mount.c:1977:2:
include/common/list.h:35:19: error: storing the address of local variable 'postpone' in
'((struct list_head *)((char *)start + 8))[24].prev' [-Werror=dangling-pointer=]
35 | new->prev = prev;
| ~~~~~~~~~~^~~~~~
criu/mount.c: In function 'mnt_tree_for_each':
criu/mount.c:1972:19: note: 'postpone' declared here
1972 | LIST_HEAD(postpone);
| ^~~~~~~~
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Setting all supported by CPU features in xstate_bv may bring it into
dirty-upper-state as documented in specs, resulting in lower
performance. Let's not do this and set only those have been used by
dumpee.
P.S.
Off course it has to be a one-liner!
Fixes: #1171
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@canonical.com>
This patch documents how do we use `make lint` and `make indent` and
adds a note about their integration with CI.
Co-authored-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Nothing serious since OS will close it anyway but still to be precise.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
New message:
ERROR: Required file /usr/lib64/libcrypto.so.3.0.1 not found.
Exiting
Old message:
File "/home/criu/coredump/criu_coredump/coredump.py", line 693, in _gen_mem_chunk
f = open(fname, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: '/usr/lib64/libcrypto.so.3.0.1'
Signed-off-by: Adrian Reber <areber@redhat.com>
This fixes errors with long command-lines:
File "/home/criu/coredump/criu_coredump/coredump.py", line 320, in _gen_prpsinfo
prpsinfo.pr_psargs = self._gen_cmdline(pid)
^^^^^^^^^^^^^^^^^^
ValueError: bytes too long (88, maximum length 80)
Signed-off-by: Adrian Reber <areber@redhat.com>
Refactor lib/py/images/images.py to reduce code duplication
by extracting repetitive code into helper functions and
private methods. This improves code readability and maintainability,
as well as reducing the risk of bugs caused by duplicated code.
Additionally, in Makefile, lib/py/images/images.py is added to the
list of files to run by flake8 during CI.
Fixes: #340
Signed-off-by: Kouame Behouba Manasse <behouba@gmail.com>
In a previous commit, we set the default runtime to runc and
"manage-cgroups" to ignore. We remove the installation script
for crun as it is not used with this test.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch disables the checkpoint/restore of cgroups for
the tests using Podman as a temporary workaround for
https://github.com/checkpoint-restore/criu/issues/2091
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This addresses Andrei comments from
https://github.com/checkpoint-restore/criu/pull/2064
- Add comment about '\n' fixing
- Replace ret with more self explainting is_read
- Print warings if we failed to print comm for some reason
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In Python 3 b'' == '' is False. This causes the info action to fail with
File "/usr/lib/python3.11/site-packages/crit-3.17-py3.11.egg/pycriu/images/images.py", line 178, in count
size, = struct.unpack('i', buf)
^^^^^^^^^^^^^^^^^^^^^^^
struct.error: unpack requires a buffer of 4 bytes
Reported-by: Sankalp Acharya (@sankalp-12)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When error happens on file dumping stage the only information about the
task we dumping is its PID. For debug purpose show task's @comm early.
It proves useful when trying to understand which of dumped applications
is "guilty" in brokern dump when pid is not there anymore.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If we build tags for our repo:
[criu]$ make tags
GEN tags
And then run codespell, we get an error:
[criu]$ codespell
./tags:3755: struc ==> struct
Let's exclude tags file from codespell search, this would add usability
to `make lint`.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The --ghost-fiemap option was introduced with #1963.
It enables an optimized algorithm based on fiemap ioctl that can reduce
the number of syscalls used to checkpoint highly sparse ghost files. This
option is enabled by default. It can be disabled with --no-ghost-fiemap
when using SEEK_HOLE/SEEK_DATA is preferred. In addition, an automatic
fallback to SEEK_HOLE/SEEK_DATA is used for filesystems that do not
supporting fiemap.
Co-authored-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Just creates ipv4/ipv6 raw/dgram sockets with IP_PKTINFO and IP_FREEBIND
socket options enabled/disabled and checks that these options persist.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We see systemd-resolved relying on these options, and after migration
the options are lost and systemd-resolved stops serving dns requests.
The socket options make kernel add cmsg with destination address to
packets, see more how systemd-resolved uses them:
00a60eaf5f/src/resolve/resolved-manager.c (L826)
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The IP_FREEBIND option is supported for RAW sockets, why not save it
while we do this for other ip sockets anyway?
One difference is that for SOCK_RAW there is no fallback between
IP_FREEBIND and IPV6_FREEBIND, see:
ef4d3ea405/net/ipv6/ipv6_sockglue.c (L1497)
So let's have explicit IPV6_FREEBIND for ipv6.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If we can't access a map_files entry directly and instead have to follow
the link and access the file via a filesystem path we need to properly
deal with files on btrfs subvolumes.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
CAP_CHECKPOINT_RESTORE does not give access to /proc/$pid/map_files in
user namespaces. In order to test that CRIU in unprivileged mode can
dump and restore anonymous shared memory pages we will run the maps00
tests in a user namespace.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
If we don't have access to map_files and instead have to get the data
from /proc/$pid/mem we can close and reset the fd before passing it to
do_dump_one_shmem() which can then check it before trying to seek past
holes, eliminating the need for a separate seek_data_supported boolean.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
This is done to follow 'Linux kernel coding style', same change was
added to .clang-format in linux kernel source recently:
d7f6604341
We don't change it in current code base but let's follow it in all
future uses.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Simplify code a bit: make exit codes of those functions more
transparent, rename ret to exit_code.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Checking errno in outer function is really strange, also saving errno of
mount syscall after calling pr_perror is completely wrong. So let's try
to simplify things.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We see that when lint is called for push action git has only one last
commit which makes make indent with git-clang-format fail to operate.
Fix it by increasing fetch depth to one more commit.
Fixes: #2066
Fixes: d6db3333a ("clang-format: rework make indent to check specific commits")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If trying to open /proc/$pid/map_files/x-x for a given VMA fails with
EPERM (can happen in unprivileged mode when running in a non-init user
ns), fall back to reading the content from /proc/$pid/mem.
Co-authored-by: Ivanq <imachug@yandex.ru>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
This patch sets VMA_AREA_REGULAR on hugetlb and anon shmem VMAs since
they can be handled the same way as other kinds of regular memory.
Co-authored-by: Ivanq <imachug@yandex.ru>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
We see that libbsd redefines __has_include to be always true, which
breaks such checks for rseq. The idea behind this patch is to put all
uses of libbsd functions to separate c files and only export wrapper
functions for them.
Using __setproctitle and __setproctitle_init everywhere in existing
code:
git grep --files-with-matches "setproctitle" | xargs sed -i 's/setproctitle/__setproctitle/g'
git grep --files-with-matches "setproctitle_init" | xargs sed -i 's/setproctitle_init/__setproctitle_init/g'
Fixes: #2036
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We see that libbsd redefines __has_include to be always true, which
breaks such checks for rseq. The idea behind this patch is remove the
use of libbsd functions and always export our replacement functions.
Using __strlcat and __strlcpy everywhere in existing code:
git grep --files-with-matches "strlcat" | xargs sed -i 's/strlcat/__strlcat/g'
git grep --files-with-matches "strlcpy" | xargs sed -i 's/strlcpy/__strlcpy/g'
Fixes: #2036
Suggested-by: Andrei Vagin <avagin@google.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
As our pr_* functions are complex and can call different system calls
inside before actual printing (e.g. gettimeofday for timestamps) actual
errno at the time of printing may be changed.
Let's just use %s + strerror(errno) instead of %m with pr_* functions to
be explicit that errno to string transformation happens before calling
anything else.
Note: tcp_repair_off is called from pie with no pr_perror defined due to
CR_NOGLIBC set and if I use errno variable there I get "Unexpected
undefined symbol: `__errno_location'. External symbol in PIE?", so it
seems there is no way to print errno there, so let's just skip it.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
As our pr_* functions are complex and can call different system calls
inside before actual printing (e.g. gettimeofday for timestamps) actual
errno at the time of printing may be changed.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This kernel feature contained some bugs initially. Those logs are useful in identifing what the
underlaying issue is and which kernel patch to backport.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
This way we can check that mount tree topology (including sharing
groups) is the same before and after c/r.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Now we can compare mount tree and sharing group tree topology before and
after c/r with mntns_compare() helper.
Algorithm here is:
1) build mount tree based on mnt_id and parent_mnt_id from mountinfo
2) sort mount tree children based on path comparison
3) at the same time set topology_id for mounts by DFS order and order
mounts in list accordingly
4) build shared groups tree based on sharing_id and master_id
5) at the same time set topology_id for sharings as smallest topology_id
of its mounts, also sharings are put in their list in order of
their topology_id
6) walk sorted mounts lists for both namespaces simultaneously each
pair of moutns should have matching ids and parent ids
7) walk sorted sharings lists for both namespaces simultaneously each
pair of sharings should have matching ids and parent ids
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
For mount testing it is nice to be able to parse mountinfo from zdtm
test itself, for instance to be able to compare mountinfo topology
before and after c/r, or for anything else. So let's add a helper
mntns_parse_mountinfo() which parses current mount namespace mountinfo.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Need it to use linux lists in zdtm.
Also copy container_of from comiler.h to zdtmtst.h like we already do
for e.g. __stack_aligned__ macro.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previousely "make indent" checked all files in criu source directory for
codding style flaws. We have several problems with it:
- clang-format default format sometimes changes in new versions of the
package and we need to reformat all our code base each time it happens
- on different systems we may have different versions of clang-format
and on latest criu-dev "make indent" may be still unhappy on your system
- when we want to update clang-format rules ourselves we need to update
all our code base each time
- sometimes clang-format rules are not fitting all our cases, (e.g.: an
option IndentGotoLabels works nice for simple C code, but is a no go for
assembler and C macros) and putting "clang-format off" everywhere is a
mess
- sometimes we intentionally want to break clang-format rules (e.g.:
we want to put function arguments on a new line separating them
"logically" not "mechanically" following 120-char rule like clang-format
does).
This adds a BASE option for "make indent" where all commits in range
BASE..HEAD would be checked with git-clang-format for codding style
flaws. For instance when developing on top of criu-dev, one can use
"make BASE=origin/criu-dev indent" to check all their commits for
compliance with the clang-format rules. Default base is HEAD~1 to make
last commit checked when "make indent" is called. The closest thing to
the old behaviour would then be "make indent BASE=init", note that only
commited files would be checked.
Extra options to git-clang-format may be passed through OPTS variable.
Also reuse "make indent" in github lint workflow.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The command ./zdtm.py list currently fails with
if opts['rootless']:
~~~~^^^^^^^^^^^^
KeyError: 'rootless'
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
memory.kmem.limit_in_bytes has been deprecated. Look at e7c4184164f7
("memcg, kmem: further deprecate kmem.limit_in_bytes") for more details.
Signed-off-by: Andrei Vagin <avagin@google.com>
Restoring SO_MARK requires root or CAP_NET_ADMIN. If the value
is 0 we will avoid dumping it so that we don't need to do a
privileged call on restore.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
SO_SNDBUFFORCE/SO_RCVBUFFORCE require root or CAP_NET_ADMIN.
We can use SO_SNDBUF/SO_RCVBUF in some cases and avoid
needing elevated privileges.
This patch renames sk_setbufs() to sk_setbufs_ns() and
makes sk_setbufs() a general helper that sets socket
send and receive buffer sizes. The helper tries to use
SO_SNDBUFFORCE/SO_RCVBUFFORCE first and falls back to
SO_SNDBUF/SO_RCVBUF if we're in unprivileged mode.
The existing sk_setbufs_ns() which takes a pid parameter
and is intended to be called via userns_call() is rewritten
to call sk_setbufs().
Existing code that sets buffer sizes via setsockopt() is
modified to call sk_setbufs() instead.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
ghost_multi_hole00 and ghost_multi_hole01 are tests which create a ghost file
with a lot of holes, there are 4K data and 4K hole inside every 8K length.
The only difference between them is ghost-fiemap option, 01 is a
test for the fiemap dumping algorithm, and we want to test the
behavior of EXTENT_MAX_COUNT part, so the file size should be 8M, thus there
will be 1024 chunks in the ghost file.
In some file system, such as xfs, we somehow can not easily create highly sparse
file as in ext4 or btrfs, therefore we need `fallocate` to forcibly create holes.
Signed-off-by: Liang-Chun Chen <featherclc@gmail.com>
In order to reduce the frequency of using system call, based on
https://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git/tree/misc/create_inode.c#n519,
I created a new algorithm of dumping chunk via fiemap.(copy_file_to_chunks_fiemap)
Also, I added another BOOL_OPT for users to determine which algorithm they
want to use. Moreover, for those filesystem not supporting fiemap, criu
will fall back to the original algorithm(SEEK_HOLE/SEEK_DATA).
v2: don't call copy_chunk_from_file on outstanding extent; rearange
headers to workaround "redeclaration of ‘enum fsconfig_command’" problem
Signed-off-by: Liang-Chun Chen <featherclc@gmail.com>
This patch fixes applies the changes required by clang-format v15.0.5
for `make indent`.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The python3 package in Alpine has recently been updated to install
symbolic link for /usr/bin/python.
https://git.alpinelinux.org/aports/commit/main/python3?id=d91da210b1614eb75517d59b7f348fee01699f35
This causes the following error in CI:
Step 10/11 : RUN ln -s /usr/bin/python3 /usr/bin/python
---> Running in a5a94be9dc93
ln: failed to create symbolic link '/usr/bin/python': File exists
The command '/bin/sh -c ln -s /usr/bin/python3 /usr/bin/python' returned a non-zero code: 1
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The way ShellCheck is installed was changed in commit c056f99
(ci/gha/lint: install a recent shellcheck) to use the latest version
v0.8.0 and remove some of the "shellcheck disable=..." annotations.
Since then, Fedora 37 has been released and the ShellCheck package
has been updated to v0.8.0.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
While building on a machine that has a HOL clang compiler,
I ran into warnings regarding the changed line. It appears
this warning is on by default because of anticipated changes
to the C standard.
Signed-off-by: Drew Wock <ajwock@gmail.com>
This patch adds a missing definition for `__nmk_dir` in the Makefile
for the amdgpu plugin. This definition is required, for example, when
building the `test_topology_remap` target:
make -C plugins/amdgpu/ test_topology_remap
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Zombie tasks are dumped in dump_zombies() so it is redundant to handle them
in dump_one_task().
Deprecate cg_set in task_core_entry as this field must be per thread now.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Some users on Raspberry Pi report that the kerndat checking for
memfd_create(MFD_HUGETLB) support returns ENOSYS even when memfd_create
syscall is available. We currently treat this error as unexpected and
return error. This commit marks the memfd_create(MFD_HUGETLB) as
unavailable when ENOSYS is returned.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
A previous commit added a cgroup cpuset unmounting to
scripts/ci/Makefile. We are sometimes running in a container without the
necessary privileges to unmount certain cgroups.
This commit moves the cgroup unmounting to a place in run-ci-tests.sh
which already requires privileged access and does not break unprivileged
build-only CI runs.
Signed-off-by: Adrian Reber <areber@redhat.com>
As cgroupv2_00, cgroupv2_01 need cpuset in cgroup-v2 hierarchy to check CRIU
handle cgroup-v2 properly, umount cpuset in cgroup-v1 to make it move to
cgroup-v2.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
This test creates a process with 2 threads in different threaded controllers and
check if CRIU restores these threads' cgroup controllers properly.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
As threads in a process may be in different threaded controllers, we need to
move thoses threads to the correct controllers.
Because the threads of a process are restored in later stage in restorer.c, we
need to create a cgroupd service to help to move those threads into correct
controllers when they are restored. We cannot use usernsd as the code in
restorer does not know the address of outside function to pass to userns_call.
However, this cgroupd service still reuses a lot of code from usernsd.
The main logic is that restored threads receive the cg_set number they belong to
before restorer stage in case their cg_set are different from main thread. When
these threads are restored, they send the cg_set number and their thread ids
through unix socket to cgroupd. cgroupd receives the cg_set number and thread
ids and moves those threads into correct controllers. Thread ids are sent
through SCM_CREDENTIALS of unix socket so they are translated into correct
thread ids in the receiving end.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Currently, we assume all threads in process are in the same cgroup controllers.
However, with threaded controllers, threads in a process may be in different
controllers. So we need to dump cgroup controllers of every threads in process
and fixup the procfs cgroup parsing to parse from self/task/<tid>/cgroup.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
This commit supports checkpoint/restore some new global properties in cgroup-v2
cgroup.subtree_control
cgroup.max.descendants
cgroup.max.depth
cgroup.freeze
cgroup.type
Only cgroup.subtree_control, cgroup.type need some more code to handle.
cgroup.subtree_control value needs to be set with "+", "-" prefix and
cgroup.type can only be written with value "threaded" if we want to make this
controller threaded. cgroup.type is a special property because this property
must be restored before any processes can move into this controller.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
It seems like drone.io no longer provides free aarch64/armhf CI runs.
This switches the aarch64 CI runs to Cirrus CI. armhf CI runs have been
dropped for now as they are not directly supported.
Signed-off-by: Adrian Reber <areber@redhat.com>
Since commit 5563cabdde, user with
enough capability can open IPC sysctl files and write to them. Therefore, we
don't need to use usernsd process in the outside user namespace to help with
that anymore. Furthermore, some later commits:
1f5c135ee5,
0889f44e28 bind the IPC namespace to
the opened file descriptor of IPC sysctl at the open() time, the changed value
does not depend on the IPC namespace of write() time anymore. This breaks the
current usernsd approach.
So, we prioritize opening/writing IPC sysctl files in the context of restored
process directly without usernsd help. This approach succeeds in the newer
kernel since the restored process has enough capabilities at this restore stage.
With older kernel, the open() fails and we fallback to the usernsd approach.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
In Virtuozzo we've faced out-of-bound access when calling this function
on short path string, which corrupted other memory and lead to
segmentation fault. So it may be useful to have this comment in code to
avoid such a missuse of this function in future.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
These are the minimal changes to make zdtm.py successfully run the
env00 and pthread test case as non-root using the '--rootless' zdtm option.
Co-authored-by: Younes Manton <ymanton@ca.ibm.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
This adds the non-root section and information about the parameter
--unprivileged to the man page.
Co-authored-by: Anna Singleton <annabeths111@gmail.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Anna Singleton <annabeths111@gmail.com>
This patch modifies how kerndat is handled in unprivileged mode.
Initialization and functionality that can only be done as root is
made separate from common code. The kerndat file's location is
defined as $XDG_RUNTIME_DIR/criu.kdat in unprivileged mode. Since
we expect that directory to be on tmpfs we maintain the same behavior
as the root-mode kerndat which lives in /run.
Co-authored-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
This commit enables checkpointing and restoring of applications as
non-root.
First goal was to enable checkpoint and restore of the env00 and
pthread00 test case.
This uses the information from opts.unprivileged and opts.cap_eff to
skip certain code paths which do not work as non-root.
Co-authored-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
This adds the function check_caps() which checks if CRIU is running
with at least CAP_CHECKPOINT_RESTORE. That is the minimum capability
CRIU needs to do a minimal checkpoint and restore from it.
In addition helper functions are added to easily query for other
capability for enhanced checkpoint/restore support.
Co-authored-by: Younes Manton <ymanton@ca.ibm.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
The idea behind the rootless CRIU code is, that CRIU reads out its
effective capabilities and stores that in the global opts structure.
Different parts of CRIU can then, based on the existing capabilities,
automatically enable or disable certain code paths.
Currently at least CAP_CHECKPOINT_RESTORE is required. CRIU will not
start without this capability.
Signed-off-by: Adrian Reber <areber@redhat.com>
python2-future, python2-junit_xml, python-flake8 and libbsd-devel are
now provided from EPEL.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The ppc64le ABI allows functions to store data in caller frames.
When initializing the stack pointer prior to executing parasite code
we need to pre-allocating the minimum sized stack frame before
jumping to the parasite code.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
Some ABIs allow functions to store data in caller frame, which
means that we have to allocate an initial stack frame before
executing code on the parasite stack.
This test saves the contents of writable memory that follows the stack
after the victim has been infected but before we start using the
parasite stack. It later checks that the saved data matches the
current contents of the two memory areas. This is done while the
victim is halted so we expect a match unless executing parasite code
caused memory corruption. The test doesn't detect cases where we
corrupted memory by writing the same value.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
return zero on chk success
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Co-authored-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Starting the daemon is the first time we run code in the victim
using the parasite stack.
It's useful for testing to be able to infect the victim without starting
the daemon so that we can inspect the victim's state, set up stack
guards, and so on before stack-related corruption can happen.
Add compel_infect_no_daemon() to infect the victim but not start the
daemon and compel_start_daemon() to start the daemon after the victim
is infected.
Add compel_get_stack() to get the victim's main and thread parasite
stacks.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
In fact an array (aptly named array) is already used in run_test2,
so let's just make it an array right from the start.
While at it, remove ls invocation.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This basically replaces
for x in $(sed ...); do
with
sed ... | while IFS= read -r x; do
The only caveat is, sed program was amended to remove empty lines
(there was one right above the PB_AUTOGEN_STOP).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This is a preferred way of fixing SC2086 shellcheck warning.
Note that since ZDTM_OPTS is passed as a string (via make or docker),
we are converting it to an array using read -a.
Remove all "shellcheck disable=SC2086" annotations.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Instead of using shellcheck v0.7.2 from fedora repo,
let's install the latest version (v0.8.0).
This allows to remove some "shellcheck disable=..." annotations,
and (I hope) better checking quality overall.
While at it, remove findutils from dnf install as this package is
already installed.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
When we restore a shell-job we would inherit tty-s, so even if we don't
have a right mount for it in container on dump, on restore it should
just be right.
Else when dumping second time via criu-ns we get:
(00.005678) Error (criu/files-reg.c:1710): Can't lookup mount=29 for fd=0 path=/dev/pts/20
Fixes: #1893
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
When we are restoring in new pidns we specifically do setsid() from
criu-ns init so that sids of restored tasks are non-zero in this pidns
and on next dump CRIU would not have problems with zero sids, see [1].
But after this CRIU tries to inherit and setup a tty for the restored
process, and it fails to set it's process group via TIOCSPGRP to be a
foreground group for it's tty, because tty already is a controlling tty
for other session (which we had before setsid).
So to make it restore we need to reset tty to be a controlling tty of
criu-ns init via TIOCSCTTY before calling criu.
Else when restoring first time via criu-ns (from criu-ns dump) we get:
Error (criu/tty.c:689): tty: Failed to set group 40816 on 0: Inappropriate ioctl for device
https://github.com/checkpoint-restore/criu/issues/232 [1]
v2: add why and what comment in code, set controlling tty only for
--shell-job and fail if stdin is not a tty.
Fixes: #1893
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
A recent change in glibc introduced `enum fsconfig_command` [1] and as a
result the compilation of criu fails with the following errors
In file included from criu/pie/util.c:3:
/usr/include/sys/mount.h:240:6: error: redeclaration of 'enum fsconfig_command'
240 | enum fsconfig_command
| ^~~~~~~~~~~~~~~~
In file included from /usr/include/sys/mount.h:32:
criu/include/linux/mount.h:11:6: note: originally defined here
11 | enum fsconfig_command {
| ^~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:242:3: error: redeclaration of enumerator 'FSCONFIG_SET_FLAG'
242 | FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */
| ^~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:12:9: note: previous definition of 'FSCONFIG_SET_FLAG' with type 'enum fsconfig_command'
12 | FSCONFIG_SET_FLAG = 0, /* Set parameter, supplying no value */
| ^~~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:244:3: error: redeclaration of enumerator 'FSCONFIG_SET_STRING'
244 | FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */
| ^~~~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:14:9: note: previous definition of 'FSCONFIG_SET_STRING' with type 'enum fsconfig_command'
14 | FSCONFIG_SET_STRING = 1, /* Set parameter, supplying a string value */
| ^~~~~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:246:3: error: redeclaration of enumerator 'FSCONFIG_SET_BINARY'
246 | FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */
| ^~~~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:16:9: note: previous definition of 'FSCONFIG_SET_BINARY' with type 'enum fsconfig_command'
16 | FSCONFIG_SET_BINARY = 2, /* Set parameter, supplying a binary blob value */
| ^~~~~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:248:3: error: redeclaration of enumerator 'FSCONFIG_SET_PATH'
248 | FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */
| ^~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:18:9: note: previous definition of 'FSCONFIG_SET_PATH' with type 'enum fsconfig_command'
18 | FSCONFIG_SET_PATH = 3, /* Set parameter, supplying an object by path */
| ^~~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:250:3: error: redeclaration of enumerator 'FSCONFIG_SET_PATH_EMPTY'
250 | FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */
| ^~~~~~~~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:20:9: note: previous definition of 'FSCONFIG_SET_PATH_EMPTY' with type 'enum fsconfig_command'
20 | FSCONFIG_SET_PATH_EMPTY = 4, /* Set parameter, supplying an object by (empty) path */
| ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:252:3: error: redeclaration of enumerator 'FSCONFIG_SET_FD'
252 | FSCONFIG_SET_FD = 5, /* Set parameter, supplying an object by fd */
| ^~~~~~~~~~~~~~~
criu/include/linux/mount.h:22:9: note: previous definition of 'FSCONFIG_SET_FD' with type 'enum fsconfig_command'
22 | FSCONFIG_SET_FD = 5, /* Set parameter, supplying an object by fd */
| ^~~~~~~~~~~~~~~
/usr/include/sys/mount.h:254:3: error: redeclaration of enumerator 'FSCONFIG_CMD_CREATE'
254 | FSCONFIG_CMD_CREATE = 6, /* Invoke superblock creation */
| ^~~~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:24:9: note: previous definition of 'FSCONFIG_CMD_CREATE' with type 'enum fsconfig_command'
24 | FSCONFIG_CMD_CREATE = 6, /* Invoke superblock creation */
| ^~~~~~~~~~~~~~~~~~~
/usr/include/sys/mount.h:256:3: error: redeclaration of enumerator 'FSCONFIG_CMD_RECONFIGURE'
256 | FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */
| ^~~~~~~~~~~~~~~~~~~~~~~~
criu/include/linux/mount.h:26:9: note: previous definition of 'FSCONFIG_CMD_RECONFIGURE' with type 'enum fsconfig_command'
26 | FSCONFIG_CMD_RECONFIGURE = 7, /* Invoke superblock reconfiguration */
This patch adds definition for FSOPEN_CLOEXEC to solve this problem. In particular,
sys/mount.h includes ifndef check for FSOPEN_CLOEXEC surrounding `enum fsconfig_command`.
[1] https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=7eae6a91e9b1670330c9f15730082c91c0b1d570
Reported-by: Younes Manton (@ymanton)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch changes top-level OpenJ9 filename and data references to Java
to make them generic and launches tests against both HotSpot and OpenJ9
JVMs.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
Semeru builds (which use OpenJ9 instead of HotSpot) are the successors
of AdoptOpenJDK's OpenJ9 builds.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
We used to pull AdoptOpenJDK's OpenJ9 builds but switched to
Eclipse Temurin, which uses the HotSpot VM instead of OpenJ9.
Rename the corresponding Dockerfiles to hotspot.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
The entry "build/" will ignore any directory named "build" at any level
of the source tree, including our scripts/build directory. We only want
to ignore the top-level build directory created by `make install`.
As the git manpage suggests, entries with slashes at the start or in the
middle will only match at the same level as the .gitignore, hence use
build/** instead.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
This allows to make test code more compact:
if (ret == -1) {
pr_perror("XXX");
return 1;
}
vs
if (ret == -1)
return pr_perror("XXX");
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Before this change, CRIU would just lose that data upon migration. So
it's better to fail migration in this case.
To reproduce the bug one can:
1. Create an AF_UNIX socket and call listen on it.
2. Create a second AF_UNIX socket and call connect to the first one.
3. Send the data to the second socket.
4. Migrate.
5. Call accept on the first socket and then read. There would be no data
available.
It should be even possible to close the second socket before migration.
This would cause accept to hang because CRIU totally misses a closed
in-flight socket.
Signed-off-by: Michal Clapinski <mclapinski@google.com>
The x86 implement hardware breakpoint to accelerate the tracing syscall
procedure instead of `ptrace(PTRACE_SYSCALL)`. The arm64 has the same
capability according to <<Learn the architecture: Armv8-A self-hosted
debug>>[[1]].
<<Arm Architecture Reference Manual for A-profile architecture>[[2]]
illustrates the usage detailly:
- D2.8 Breakpoint Instruction exceptions
- D2.9 Breakpoint exceptions
- D13.3.2 DBGBCR<n>_EL1, Debug Breakpoint Control Registers, n
Note:
[1]: https://developer.arm.com/documentation/102120/0100
[2]: https://developer.arm.com/documentation/ddi0487/latest
Signed-off-by: fu.lin <fulin10@huawei.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Breakpoints are used to stop as close as possible to a target system call.
First, we don't need it after this point.
Second, PTRACE_CONT can't pass through a breakpoint on arm64.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
When delivering system call traps, set bit 7 in the signal number (i.e.,
deliver SIGTRAP|0x80). This makes it easy for the tracer to distinguish
normal traps from those caused by a system call.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
1. Rename CentOS 8 to CentOS Stream 8 (which it is).
2. Install junit_xml from the repo rather than via pip.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Mostly a copy-paste from the CentOS 8 task, with a few differences:
- Use dnf instead of yum
- Enable crb instead of powertools
- Different way of installing EPEL
- No need to switch to python3 as this is the default
- junit_xml is now available as an rpm
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
There is a race condition in docker/containerd that causes docker to
occasionally fail when starting a container from a checkpoint immediately
after the checkpoint has been created.
This problem is unrelated to criu and has been reported in
https://github.com/moby/moby/issues/42900
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Let's use dynamic approach to detect built-in *libc rseq in all cases,
and "old" static approach as a fallback path if the user kernel
lacks support of ptrace_get_rseq_conf feature.
Suggested-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Before this patch we assumed that CRIU is compiled against
the same GLibc as it runs with. But as we see from real
world examples like #1935 it's not always true.
The idea of this patch is to detect rseq configuration
for the main CRIU process and use it to unregister
rseq for all further child processes. It's correct,
because we restore pstree using clone*() syscalls,
don't use exec*() (!) syscalls, so rseq gets inherited
in the kernel and rseq configuration remains the same
for all children processes.
This will prevent issues like this:
https://github.com/checkpoint-restore/criu/issues/1935
Suggested-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
The result of check_aa_ns_dumping() is stored in kdat. Instead of doing
the same check twice - once on kerndat_init(), and again in
check_apparmor_stacking(), we can check the stored value.
Suggested-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The feature check for AppArmor stacking was introduced in
commit:
8723e3f998
check: add a feature test for apparmor_stacking
However, on systems that don't support AppArmour, this check always
fails. As a result, `criu check --all` shows the following message:
Looks good but some kernel features are missing
which, depending on your process tree, may cause
dump or restore failure.
Reported-by: André Rösti (@andrej)
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
In commits [1, 2] the version of containerd installed by default in the
GitHub CI virtual environment was replaced with the latest release from
GitHub as a workaround to a bug in containerd. This bug has been fixed
sometime ago and the current default version of containerd (1.6.6) does
not require this workaround. However, with the latest release, the
containerd binaries uploaded on GitHub have been built for Ubuntu 22.04
[3]. Our tests are still running on Ubuntu 20.04 and this results in the
following error:
/usr/bin/containerd: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.34' not found (required by /usr/bin/containerd)
/usr/bin/containerd: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.32' not found (required by /usr/bin/containerd)
[1] 046cad8
[2] 81a68ad
[3] 6b2dc9a37
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
There are several changes in glibc 2.36 that make sys/mount.h header
incompatible with kernel headers:
https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E
This patch removes conflicting includes for `<linux/mount.h>` and
updates the content of `criu/include/linux/mount.h` to match
`/usr/include/sys/mount.h`. In addition, inline definitions sys_*()
functions have been moved from "linux/mount.h" to "syscall.h" to
avoid conflicts with `uapi/compel/plugins/std/syscall.h` and
`<unistd.h>`. The include for `<linux/aio_abi.h>` has been replaced
with local include to avoid conflicts with `<sys/mount.h>`.
Fixes: #1949
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
We need to pass environment variables from the CI environment to
distinguish between CI environments. However, when `sudo -E` is
used to run Podman it results in the XDG_RUNTIME_DIR environment
variable being set incorrectly that prevents Podman from running.
This patch fixes the following error in the GitHub Action virtual
environment:
error running container: error from /usr/bin/crun creating
container for [/bin/sh -c /bin/prepare-for-fedora-rawhide.sh]:
sd-bus call: Connection reset by peer
Fixes: #1942
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
I've been contributing to CRIU for sometime and I'm hoping that my
familiarity with the project would be sufficient to self-nominate as a
maintainer. I would like to help with code reviews, submitting patches,
implementing new features, and maintaining the project in general.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
ghost_holes_large00 is a test which creates a large ghost sparse file with 1GiB
hole(pwrite can only handle 2GiB maximum on 32-bit system) and 8KiB data, criu
should be able to handle this kind of situation.
ghost_holes_large01 is a test which creates a large ghost sparse file with 1GiB
hole and 2MiB data, since 2MiB is larger than the default ghost_limit(1MiB),
criu should fail on this test.
v2: fix overflow on 32-bit arch.
Signed-off-by: Liang-Chun Chen <featherclc@gmail.com>
unlink_largefile test
In the past, the unlink_largefile test should be fail on large ghost file.
However, it used sparse file, it will pass in current criu, since the large
ghost sparse file issue was fixed.
So the crfail flag of this test should be removed.
Signed-off-by: Liang-Chun Chen <featherclc@gmail.com>
files-reg.c checks whether the file size is larger than ghost_limit with st_size
(in dump_ghost_remap), which can not deal with large ghost sparse file, since
its actual file size is not the same as what st_size shows.
Therefore, in this commit, I replace st_size with st_blocks, which shows the
actual file size. (1 block = 512B), thus criu can deal with large ghost sparse
file.
Signed-off-by: Liang-Chun Chen <featherclc@gmail.com>
This test specifically wants to create external bind-mount of "/" from
criu mntns to test mntns, and it wants "/" in criu mntns to be a shared
mount so that "external" mount in the test mntns is it's slave. This is
to triger specific dirname() resolution which happens only when sharing
restore is involved for external mounts, and only if rootfs is involved.
But initially I missed that when we create external mount in test's
temporary mntns it creates a propagation in criu mntns on top of root
mount. This mount may influence other tests restore as child mount in
root mount converts to locked child mount in criu service mntns (for uns
flavour) and when criu would restore root container mount it would fail
with EINVAL on non recursive bind with locked children.
To fix this mess we just need to prohibit propagating from tests
temporary mntns to criu mntns by making mounts slave.
Fixes: #1941
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If root mount in criu mntns is slave, it would be slave of host mount
where criu is stored, so if someone mounts something in subdir of
{criu-dir}/test/ on host while tests are running this mount can
influence the test as it appears on top of root mount in criu mntns.
1) With mount-compat this mount can get into restored test mntns, which
means wrong restore, as this mount was not there on dump.
2) With mount-v2 this mount would just fail container restore, as root
container mount is mounted non-recursively to protect from unexpected
mounts appear after restore.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On Arch Linux with 5.18.3-zen1-1-zen kernel, the vdso's size is 3 pages which
exceeds the current 2-page reserved buffer. This commit simply increases the
reserved buffer size to 4 pages.
Fixes: https://github.com/checkpoint-restore/criu/issues/1916
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Normally, vsyscall vma has VM_READ, VM_EXEC permission. However, when
CONFIG_LEGACY_VSYSCALL_XONLY=y, that vma only has VM_EXEC. This commit removes
the permission part when checking to skip vsyscall vma in x32 tests.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Error from:
./test/zdtm.py run -t zdtm/static/fpu00 --fault 134 -f h --norst
(00.003111) Dumping GP/FPU registers for 56
(00.003121) Error (compel/arch/x86/src/lib/infect.c:310): Corrupting fpuregs for 56, seed 1651766595
(00.003125) Error (compel/arch/x86/src/lib/infect.c:314): Can't set FPU registers for 56: Invalid argument
(00.003129) Error (compel/src/lib/infect.c:688): Can't obtain regs for thread 56
(00.003174) Error (criu/cr-dump.c:1564): Can't infect (pid: 56) with parasite
See also:
145e9e0d8c6 ("x86/fpu: Fail ptrace() requests that try to set invalid MXCSR values")
145e9e0d8c
We decided to move from mxcsr cleaning up scheme and use mxcsr mask
(0x0000ffbf) as kernel does. Thanks to Dmitry Safonov for pointing out.
Tested-on: Intel(R) Xeon(R) CPU E3-1246 v3 @ 3.50GHz
Reported-by: Mr. Jenkins
Suggested-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
1. For some reason, Marier distribution headers
not correctly define __GLIBC_HAVE_KERNEL_RSEQ
compile-time constant. It remains undefined,
but in fact header files provides corresponding
rseq types declaration which leads to conflict.
2. Another issue, is that they use uint*_t types
instead of __u* types as in original rseq.h.
This leads to compile time issues like this:
format '%llx' expects argument of type 'long long unsigned int', but argument 5 has type 'uint64_t' {aka 'long unsigned int'}
and we can't even replace %llx to %PRIx64 because it will break
compilation on other distros (like Fedora) with analogical error:
error: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 6 has type ‘__u64’ {aka ‘long long unsigned int’}
Let's use our-own struct rseq copy fully equal to the kernel one,
it's safe because this structure is a part of Linux Kernel ABI.
Fixes#1934
Reported-by: Nikola Bojanic
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Add a simple test using tail to check that processes can't be restored
by default when the r/w/x mode of an open file changes, unless
--skip-file-rwx-check is used.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
A file's r/w/x changing between checkpoint and restore does
not necessarily imply that something is wrong. For example,
if a process opens a file having perms rw- for reading and
we change the perms to r--, the process can be restored and
will function as expected.
Therefore, this patch adds an option
--skip-file-rwx-check
to disable this check on restore. File validation is unaffected
and should still function as expected with respect to the content
of files.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
stopped03 check that stopped by SIGTSTP tasks are restored correctly.
stopped04 check that stopped by SIGSTOP tasks which have blocked SIGTSTP and
have SIGTSTP pending are restored correctly.
Signed-off-by: Yuriy Vasiliev <yuriy.vasiliev@openvz.org>
Add SIGTSTP signal dump and restore. Add a corresponding field
in the image, save it only if a task is in the stopped state.
Restore task state by sending desired stop signal if it is present
in the image. Fallback to SIGSTOP if it's absent.
Signed-off-by: Yuriy Vasiliev <yuriy.vasiliev@openvz.org>
Else we trigger BUG in task_reset_dirty_track():
Error (criu/mem.c:45): BUG at criu/mem.c:45
The check in kerndat_get_dirty_track() does not work right.
https://github.com/checkpoint-restore/criu/issues/1917
Reported-by: @mrc1119
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Currently, the content of anonymous private hugetlb mapping is dumped in 2
different images: memfd approach and normal private mapping dumping. In memfd
approach, we dump the content of the backing pseudo file (/anon_hugepage). This
is incorrect and redundant since the mapping is private, the content of backing
file may differ from the content of the mapping. With this commit, we remove the
redundant memfd approach dump and only do the normal private mapping dump on
anonymous hugetlb mapping.
Run zdtm.py run -f h --keep-img always -t zdtm/static/maps09, du -h in the
dumped image directory
Before this commit
13M test/dump/zdtm/static/maps09/55/1
After this commit
8.5M test/dump/zdtm/static/maps09/55/1
The reduction in size is approximately 4MB which is the size of anonymous
private hugetlb mapping in the test.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Before this patch, if we had a unixsk with incomming scm packets (with
fds) and with the sender side fd closed, we got an error:
Error (criu/sk-unix.c:1125): unix: Can't find sender for 0x1e
First part of the problem is that unix_note_scm_rights() expects to see
a "queuer" which would send scm packets to the unixsk, and there is no
as the sender side is closed.
Second part of the problem is that we already have "fake" queuers
feature so that it already creates a unix socket pair and leaves other
end open for later queuing packets. But function add_fake_unix_queuers()
is called after unix_note_scm_rights() thus there is no chance to find
queuer at the point of failure.
Third part is that when we look for a queuer in find_queuer_for() we
actually look for a socket for which we are a queuer and not for the
socket which is a queuer for us, which is opposite to the name. For
cases where both ends are alive both are queuers for each other so this
was not important, but for our closed sender case it breaks.
So let's reorder add_fake_unix_queuers() before unix_note_scm_rights()
and make find_queuer_for() actually do what it's name implies.
This situation is started to reproduce on Virtuozzo start/stop tests
with the unixsk belonging to systemd, we suppose that this state where
the sender fd side is closed happens rarely only on systemd start/stop,
so we don't see it in regular suspend resume of long-living containers.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
criu-ns script incorrectly compares the pidns fd with mntns fd.
Also reversed the condition in is_my_namespace function to align it
with the function name.
Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
As private hugetlb mappings are not pre-mapped, the content of them is restored
in the the restorer which cannot use page_read->read_pages. As a result, we
cannot recursively read the content of pre-dumped image in the parent directory
and use preadv to read the content from the last dumped image only. Therefore,
it may freeze while restoring when the content of mapping is in pre-dumped image
in parent directory.
We need to skip pre-dumping on hugetlb mappings to resolve the issue.
Suggested-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
It can be confusing to see error from post-dump action script and non
zero return from criu though at the same time see "Dumping finished
successfully" in log. I believe it is logical to consider post-dump
action script as a part of "dump" process so fail in it means that the
whole dump failed.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
* Fixes for pre-dump read mode
* Fixes for mount-v2
* amdgpu plugin build and installation fixes
* Some minor CI related fixes
Signed-off-by: Adrian Reber <areber@redhat.com>
This test has one external mount [criumntns] /zdtm_root_ext.tmp ->
[testmntns] /mnt_root_ext.test, and it specifically gives '--external
mnt[MNT]:.zdtm_root_ext.tmp' option on restore without '/' to make
dirname on it return static '.' path (see glibc dirname() code) and
reproduce a segfault in resolve_mountpoint().
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Else we have a Segmentation fault in __move_mount_set_group() on
xfree(source_mp) if resolve_mountpoint() returned statically allocated
path.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
It's a problem when while restoring sharing group we need to copy
sharing between two mounts with non-intersecting roots, because kernel
does not allow it.
We have a case https://github.com/opencontainers/runc/pull/3442, where
runc adds different devtmpfs file-bindmounts to container and there is
no fsroot mount in container for this devtmpfs, thus mount-v2 faces the
above problem.
Luckily for the case of external mounts which are in one sharing group
and which have non-intersecting roots, these mounts likely only have
external master with no sharing, so we can just copy sharing from
external source and make it slave as a workaround.
https://github.com/checkpoint-restore/criu/issues/1886
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This helper restores master_id and shared_id of first mount in the
sharing group. It first copies sharing from either external source or
internal parent sharing group and makes master_id from shared_id. Next
it creates new shared_id when needed.
All other mounts except first are just copied from the first one.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Building the criu packages for Ubuntu/Debian fails with:
mkdir: cannot create directory '/var/lib/criu': Permission denied
This patch updates PLUGINDIR with the value /usr/lib/criu
Fixes: #1877
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When building packages for CRIU the source directory might have a
name different than 'criu'.
Fixes: #1877
Reported-by: @siris
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
* handle unexpected errors of process_vm_readv
* adjust riovs in analyze_iov
* call handle_faulty_iov only if process_vm_readv returns EFAULT.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
But actually, 5a92f100b8 probably has to be reverted as a whole.
PIPE_MAX_SIZE is the hard limit to avoid PAGE_ALLOC_COSTLY_ORDER
allocations in the kernel. But F_SETPIPE_SZ rounds up a requested pipe
size to a power-of-2 pages. It means that when we request PIPE_MAX_SIZE
that isn't a power-of-2 number, we actually request a pipe size greater
than PIPE_MAX_SIZE.
Fixes: 5a92f100b8 ("page-pipe: Resize up to PIPE_MAX_SIZE")
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Name collision with an abandoned project named 'crit' in pypi causes pip
to show crit (CRiu Image Tool) as outdated. This patch updates crit to
use the same version and license as criu.
Fixes#1878
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Amongst a huge number of fixes all over the place this release introduces:
* mount-v2 engine
* support for MAP_HUGETLB mappings
* support for Linux Restartable Sequences
* support for SOCK_SEQPACKET unix sockets
* CRIU AMD GPU plugin
* setsockopt(SO_BUF_LOCK) support for tcp sockets
Signed-off-by: Adrian Reber <areber@redhat.com>
Currently we check memfd_hugetlb by doing memfd_create("", MFD_HUGETLB).
If we see EINVAL we report that it's not supported, but we can also
get ENOENT error in such case in hugetlb_file_setup() while trying
to find proper hugetlbfs mount.
Reference:
06fb4ecfea/fs/hugetlbfs/inode.c (L1465)
Fixes: 4245e6b02f ("check: Add a check for using memfd with hugetlb")
Reported-by: Mr. Jenkins (ppc64le)
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
GitHub Actions comes with pre-installed criu in /usr. configure scripts
looking for CRIU will pickup the pre-installed version in /usr if we do
not install CI criu also in /usr.
Signed-off-by: Adrian Reber <areber@redhat.com>
bind_on_delete() return code is only used for setting errno for pr_perror()
This is mostly useless since a lot of syscalls already set it. All of
non-syscall errors already have prints in case of failure.
Fix bind_on_deleted() always returning 0 and simplify error juggling to
returning -1 in case of errors.
Fixes: #1771
Fixes: d0308e5ecc ("sk-unix: make criu respect existing files while restoring ghost unix socket fd")
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
The map_extra field has been introduced in Linux Kernel release 5.16
and does not exist in older kernel versions. The current parsing
implementation fails when map_extra is missing.
In particular, it tries to parse the `memlock` field as `map_extra` and
fails but it does not exit with an error because map_extra is marked as
"optional". It then tries to parse the `map_id` field as `memlock` and
fails with an error because map_id is not optional:
Error (criu/proc_parse.c:2161): parse_fdinfo_pid_s: error parsing [map_type:\t2] for 19: Success'
To correctly handle this, we should try to parse again the next field
when parsing of `map_extra` fails, without reading the next line from
the bpfmap.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
bpf_create_map_xattr() has been replaced with bpf_map_create()
6cfb97c
DECLARE_LIBBPF_OPTS has been renamed to LIBBPF_OPTS
ea6c242
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
It looks like we've got broken fhandles from fdinfo
for inotifies/fanotifies for btrfs. I will look into that.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
We have a separate target for alpine in script/ci/Makefile
which defines some extra opts for zdtm using ZDTM_OPTIONS
variable. But really it doesn't work. First of all, variable
should be named as ZDTM_OPTS and also we have to specify
it directly in the CONTAINER_RUNTIME cmdline to make it work.
I've also changed variable value just to make it consistent
with docker.env value which was really used.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
That's strange but rseq02 test fails with:
09:06:16.222: 51: exit 555f52082120 555f52082120
09:06:16.282: 51: exit 555f52082120 555f52082120
09:06:16.340: 51: exit 555f52082120 555f52082120
09:06:16.397: 51: exit 555f52082120 555f52082120
09:06:16.503: 51: exit 0 555f52082120
09:06:16.503: 51: FAIL: rseq02.c:235: Failed to increment per-cpu counter (errno = 2 (No such file or directory))
09:06:16.503: 51: FAIL: rseq02.c:246: (errno = 16 (Device or resource busy))
It means that rseq_cs pointer was cleaned up by the kernel despite of
NO_RESTART* flags. That's a hardly reproducible and I will investigate that.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Userspace may configure rseq cs abort policy by
setting RSEQ_CS_FLAG_NO_RESTART_ON_* flags.
In ("cr-dump: fixup thread IP when inside rseq cs") we have supported
the case when process was caught by CRIU during rseq cs execution by
fixing up IP to abort_ip. Thats a common case, but there is special flag
called RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL, in this case we have to leave
process IP as it was before CRIU seized it. Unfortunately, that's not
all that we need here. We also must preserve (struct rseq)->rseq_cs field.
You may ask like "why we need to preserve it by hands? CRIU is dumping
all process memory and restores it". That's true. But not so easy. The problem
here is that the kernel performs this field cleanup when it realized that
the process gets out of rseq cs. But during dump/restore procedures we are
executing parasite/restorer from the process context. It means that process
will get out of rseq cs in any case and (struct rseq)->rseq_cs will be cleared
by the kernel. So we need to restore this field by hands at the *last* stage
of restore just before releasing processes.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
If we caught the process when it's inside rseq
critical section we have to handle it properly.
From the kernel side of view, if the process
is executing inside the rseq cs and gets a signal,
rseq critical section execution will be interrupted
and after signal handler execution, we will proceed
to rseq cs abort handler instead of continuing normal
rseq cs execution (if RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
isn't set).
When CRIU seizes processes that's the same thing as
getting signal from the rseq point of view. So we need
to fixup instruction pointer to rseq cs abort handler
address.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Fresh Glibc does rseq() register by default. We need to unregister
rseq before registering our own.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Let's take thread_pointer() implementation from Glibc.
It will be useful in the further because Glibc stores
struct rseq on the TLS. Absolute address can be calculated
as __criu_thread_pointer() + __rseq_offset.
__rseq_offset is an exported symbol from Glibc itself.
We need to have an ability to determine where struct
rseq is stored to unregister it in CRIU during the restore
stage.
For different libc like musl-libc we will have to handle
rseq separately depends on how struct rseq is stored.
Right now that's not a problem because musl-libc has no
rseq support, so we don't need to unregister it.
https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=8dbeb0561eeb876f557ac9eef5721912ec074ea5https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=cb976fba4c51ede7bf8cee5035888527c308dfbc
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
We have ability to use nested virtualization on
Cirrus, and already have "Vagrant Fedora based test (no VDSO)"
test, let's do analogical for Fedora Rawhide to get fresh kernel.
Suggested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Here we just want to check that if rseq was registered before C/R
it remains registered after it.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
A lot of kernel versions lacks support for ptrace(PTRACE_GET_RSEQ_CONFIGURATION).
But the userspace may be fresh (for instance containers with fresh Fedora runs
on CentOS 7 host). Consider two scenarious:
- kernel has no ptrace(PTRACE_GET_RSEQ_CONFIGURATION) support
1. there is a process which use rseq => fail dump
2. there is no process which use rseq => we can dump without any problems
But how to determine if process use rseq or not without get_rseq_conf feature?
Let's just try to do rseq registration from the parasite. If rseq is already
registered then we'll got EBUSY error. If not we'll success in registration.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Support basic rseq C/R scenario. Assume that:
- there are no processes with IP inside the rseq critical section (CS)
- kernel has ptrace(PTRACE_GET_RSEQ_CONFIGURATION) support
On dump:
1. use ptrace(PTRACE_GET_RSEQ_CONFIGURATION) to get
struct rseq pointer, rseq size and signature from the kernel.
2. save to the image
On restore:
1. get rseq ptr, size, signature from the image
2. register it back using rseq() from the restorer parasite
Fixes: #1696
Reported-by: Radostin Stoyanov <radostin@redhat.com>
Suggested-by: Florian Weimer <fweimer@redhat.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Add "get_rseq_conf" feature corresponding to the
ptrace(PTRACE_GET_RSEQ_CONFIGURATION) support.
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
The code expected that the cgroup directory ends with a ',' and
unconditionally removes the last character. For the "unified" case this
resulted in the last 'd' being remove instead of the non existing comma.
This just adds a comma after "unified" so that the last removed
character is not the 'd'.
Suggested-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Those that codespell have a few variants for:
./soccr/soccr.c:219: thise ==> these, this
./soccr/soccr.c:444: sence ==> sense, since
./criu/net.c:665: ot ==> to, of, or
./criu/net.c:775: ot ==> to, of, or
./criu/files.c:1244: wan't ==> want, wasn't
./criu/kerndat.c:1141: happend ==> happened, happens, happen
./criu/mount-v2.c:781: carefull ==> careful, carefully
./test/zdtm/static/socket_aio.c:54: Chiled ==> Child, chilled
./test/zdtm/static/socket_listen6.c:73: Chiled ==> Child, chilled
./test/zdtm/static/socket_listen.c:73: Chiled ==> Child, chilled
./test/zdtm/static/socket_listen4v6.c:73: Chiled ==> Child, chilled
./test/zdtm/static/sk-unix-dgram-ghost.c:201: childs ==> children, child's
./test/zdtm/static/sk-unix-dgram-ghost.c:205: childs ==> children, child's
./compel/arch/x86/src/lib/infect.c:297: automatical ==> automatically, automatic, automated
While at it, do some other minor fixes in the same lines.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
I am not sure if this is going to bring any compatibility issues.
If yes, we need to remove this patch and add "useable" to the list of
ignored words instead.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Codespell thinks that tThe is a typo. Fix it by separating "\t"
which also includes readability (a bit).
[v2: run via make indent]
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
It is mapped, not maped. Same applies for mmap I guess.
Found by codespell, except it wants to change it to mapped,
which will make it less specific.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Codespell thinks that NODEL is a misspelled MODEL. Indeed it looks that
way. Add an underscore.
Do the same for the file names.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Codespell thinks that "inot" is a misspelled "into".
Rename to infd ("inotify fd") to make it happy.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
CRIU has a few places where it creates unix sockets and their names have to be
unique for each criu run.
Fixes: #1798
Signed-off-by: Andrei Vagin <avagin@google.com>
Since https://reviews.llvm.org/D122271, Clang -Wset-but-unused-variable
gets smarter to warn about unused post-increments.
Signed-off-by: Fangrui Song <maskray@google.com>
```
criu/apparmor.c:679:26: error: 'fscanf' may overflow; destination buffer in argument 3 has size 48, but the corresponding specifier may require size 49 [-Werror,-Wfortify-source]
ret = fscanf(f, "%48s", contents);
```
The buffer size should be at least one larger than the fscanf maximum
field width.
Fixes: 8d992a680e ("lsm: support checkpoint/restore of stacked apparmor profiles")
Signed-off-by: Fangrui Song <maskray@google.com>
The init process can exit if it doesn't have any child processes and its
pidns is destroyed in this case. CRIU dump is running in the target pid
namespace and it kills dumped processes at the end. We need to create a
holder process to be sure that the pid namespace will not be destroy
before criu exits.
Fixes: #1775
Signed-off-by: Andrei Vagin <avagin@gmail.com>
zdtm.py mounts two named controllers for tests. In CI, we run zdtm.py a few
times, so we can mount (create) these controllers once to avoid any unwanted
effects.
Signed-off-by: Andrei Vagin <avagin@google.com>
The idea that each zdtm.py should have own helder, so that two zdtm.py that are
running on the same host don't effect each other.
Fixes: #1774
Signed-off-by: Andrei Vagin <avagin@google.com>
We have three of "Can't mount at %s", let's distinguish simple mount
from bind-mount and re-mount to make log reading easier.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On pre v5.15 kernel we don't have MOVE_MOUNT_SET_GROUP support and thus
all our ci logs are filled with "fallback" messages. Let's decrease log
level to debug, so that we don't see it in ci logs.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
[root@fedora criu]# ./test/zdtm.py run -t zdtm/static/pty-console --iters 2 --keep-going --ignore-taint
[WARNING] Option --keep-going is more useful when running multiple tests
userns is supported
=== Run 1/1 ================ zdtm/static/pty-console
====================== Run zdtm/static/pty-console in uns ======================
Start test
Test is SUID
./pty-console --pidfile=pty-console.pid --outfile=pty-console.out
Run criu dump
Run criu restore
Run criu dump
=[log]=> dump/zdtm/static/pty-console/62/2/dump.log
------------------------ grep Error ------------------------
b'(00.009325) 101 fdinfo 3: pos: 0 flags: 100000/0'
b'(00.009332) Dumping path for 3 fd via self 19 [/zdtm/static]'
b'(00.009345) 101 fdinfo 4: pos: 0 flags: 100002/0'
b'(00.009352) tty: Dumping tty 20 with id 0xc'
b"(00.009358) Error (criu/files-reg.c:1710): Can't lookup mount=1647 for fd=4 path=/ptmx"
b'(00.009361) ----------------------------------------'
b'(00.009369) Error (criu/cr-dump.c:1368): Dump files (pid: 101) failed with -1'
b'(00.009696) Running network-unlock scripts'
b'(00.012401) Unfreezing tasks into 1'
b'(00.012410) \tUnseizing 86 into 1'
b'(00.012415) \tUnseizing 101 into 1'
b'(00.012428) Error (criu/cr-dump.c:1788): Dumping FAILED.'
------------------------ ERROR OVER ------------------------
################ Test zdtm/static/pty-console FAIL at CRIU dump ################
Test output: ================================
<<< ================================
Send the 9 signal to 86
Wait for zdtm/static/pty-console(86) to die for 0.100000
##################################### FAIL #####################################
Restore on second iteration with mount-v2 fails, that is because
devpts_restore which is called from do_new_mount_v2 via fstype->restore
opens ptmx file in service mntns and saves it to fdstore for later use.
So after first c/r open ptmx fd changes mnt_id in fdinfo to a detached
mount. Let's just disable mount-v2 for this test for now.
FIXME: We should create separate fstype hook to do_mount_in_right_mntns,
so that we can open files from this hook in actual restored mntns.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Let's run zdtm in jenkins with --mntns-compat-mode option and same for
device-external mount test from others.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Now when we switched to mount-v2 by default to check old mount engine we
need to explicitly run with --mntns-compat-mode option.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We can have tracefs separate mount from debugfs and that's why the
/sys/kernel/debug external mount now has children and this thing is not
supported to be bind in container with children, because we don't wan't
external mounts to introduce some unexpected extra external mounts so we
bind them without MS_REC in mount-v2 unlike in old mount engine.
We can either bind without MS_REC when constructing test or provide all
children mount as separate external mounts to criu, let's just disable
for now.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/87875c023
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Before mounts-v2 we have seen mounts loosing their mount readonly flags
when they were in a propagation group, because CRIU "forgot" to set
them, with new mount engine it should work now as all propagations are
now created on the same path there all other normal mounts are created,
and all mount flags are restored.
This test actually mounts only one mount, other three are propagations,
lets set mount ro flag for half of them.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/22584993d
FIXME: need to check options restored right as we don't have
--check-mounts to do this job for us.
Reviewed-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Mounts-v2 engine should fix multiple problems of old engine relative to
sharing options, lets add a test for such problems.
Add all four types of shared groups: 1) private, 2) shared, 3) slave
and 4) slave+shared for mounts. Propagate them into sharing and after
propagation change sharing with four ways: 1) don't change, 2) make
private, 3) make slave and 4) make private + make shared.
This brings 16 cases of different sharing options for mount propagation,
lets check that they all are restored fine.
Lets create mounts from description to make it easier to improve this
test in future.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/8bcd0034d
FIXME: need to check options restored right as we don't have
--check-mounts to do this job for us.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
These test simply checks that sharing between two mounts in container:
1) external mount and 2) it's bind persists (case when bind has the same
mountpoint).
Note: on old mount engine mounts inside container become also shared
with mount in criu mount namespace (outside container) after c/r which
is not right.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/76a09e850
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Now when we switched to mount-v2 by default to check old mount engine we
need to explicitly run with --mntns-compat-mode option.
Note that if the feature move_mount_set_group is not supported then
regular run will just fallback to old mount engine and then we don't
need separate run with --mntns-compat-mode.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e4a430e1f
Changes: prepend --mntns-compat-mode to r_opts in zdtm.py so that we
can disable this option with --no-mntns-compat-mode from test desc
files.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Design of mounts-v2:
As a preparation step we classify mounts in groups by (shared_id,
master_id) in new resolve_shared_mounts_v2 (just after reading images).
New function prepare_mnt_ns_v2 is our main entry point when switching
from old mount engine to new one actually happens.
First we pre-create each mount namespace nearly empty, only with root
yard in place (pre_create_mount_namespaces).
We walk the mount tree and mount each mount similar to old mount
engine but not in mount tree but as a sub-directory of root yard
(plain mountpoint) in service (criu) mount namespace. Also we
bind this mount from service mntns to real mntns just after creation.
(do_mount_in_right_mntns)
Note: this way we initially have the final mount which would be
visible to restored container user with right mnt_id for the sake of
e.g. creating unix sockets on it (for unix socket bindmounts), and
both have copy of the mount in service mntns so that old code which
accesses files on mounts through service mntns still can acces them.
New can_mount_now_v2 is now free from heuristics we had for restoring
shared groups, we will restore them later via MOVE_MOUNT_SET_GROUP,
for now everything is private.
Now when all plain mount are created in real mount namespaces, we can
move them to the tree for each namespace. Also we open fds on the
mountpoint: one mp_fd_id before moving and another mnt_fd_id after,
so that we can access each file later from final mntns via those fds.
(assemble_mount_namespaces)
New restore_mount_sharing_options walks each root sharing group and
their descendants with dfs tree walk. It creates sharing for the first
mount in the sharing group and then sets the same sharing on all other
mounts in this group.
Sharing creation for fist mount is two step:
a) If mount has master_id we either copy shared_id from parent sharing
group or from external source and then make mount slave thus
converting it to right master_id.
b) Next if mount has shared_id we just make us shared, creating right
shared_id.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/596651d02
Changes:
- Split all "exporting" to separate preparational patches
- Rework cr_time
- Switch to MOVE_MOUNT_SET_GROUP
- Use resolve_mountpoint for external mounts (for MOVE_MOUNT_SET_GROUP)
- Mounting plain mounts both in service and in restored-final mntns
- Call MOVE_MOUNT_SET_GROUP from usernsd
- Rework can_mount_now_v2 to handle bind of both root and external.
- Use sys_move_mount for mount assembling.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is a preparation of mounts-v2 new algorithm for mount restore, we
add an alternative mountpoints to each mount, so that if we mount mounts
in these mountpoints they will be "plain": each mount in separate
sub-directory of root_yard, mounts will be mounted without tree. Tree
reconstruction will be done in separate step.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/5e6de171a
Changes: improve get_plain_mountpoint().
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We plan to switch to Mounts-v2 engine for restoring mounts by default,
this options is to allow switching to old engine. This patch only adds
an option, no engine behind it yet.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/503f9ad2c
Changes: allow --mntns-compat-mode option only on restore and only if
MOVE_MOUNT_SET_GROUP is supported (this also requires change in
unittest/mock.c), change id in rpc criu_opts.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This helper would be useful to get mountpoints of source path of
external mounts without parsing host mountinfo. When we restore
mountpoint-external mount and we need to copy sharing from source via
MOVE_MOUNT_SET_GROUP, it would require from us to give it real
mountpoint of source path to be able to copy sharing group.
This uses openat2 RESOLVE_NO_XDEV feature which detects crossing
mountpoint boundary instead of potentially slow mountinfo parsing.
v3: coverity CID 389209: close fd only when it was opened
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Will use this for cross mount namespace bindmounts.
Note: don't need separate kdat for mount-v2, as MOVE_MOUNT_SET_GROUP
were added much later than open_tree and all related fixups.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Mounts-v2 requires new kernel feature MOVE_MOUNT_SET_GROUP to be able to
restore propagation between mounts right.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/7da7f9a17
Changes: define move_mount syscall, check mainstream kernel
MOVE_MOUNT_SET_GROUP feature, use our "linux/mount.h" to overcome
possible problems of non-existing header on older kernels.
v3: coverity CID 389201: check ret of umount2 and rmdir at cleanup stage
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
While mounts-v2 mounts all mounts plain without tree in service mntns we can't
just use path relative to mntns to find remap. Make it mount related, it is
also compatible with mounts-v1.
Also we don't need openat and unlinkat here as we've opened rmntns_root
just before that, lets switch to "non-at" variants.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/dc9ac0c80
Changes: rework to skip vz-specific hunks.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
While mounts-v2 would mount all mounts plain without tree in service
mntns we can't just use path relative to mntns to find remap. Make it
mount related, it is also compatible with current mount engine.
Also handle no-mntns case separately in nomntns_create_ghost.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/9cdf0b3e4
Changes: make gf->remap.rpath always relative else we get:
Error (criu/files-reg.c:779): Couldn't unlink remap
/tmp/.criu.mntns.BCurDL/13-0000000000 /zdtm/static/cwd02.test:
No such file or directory
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Will use it to make create_ghost work with mount-v2.
Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/156fa4877
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/069bba0ad
Changes: merge fixup.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This getter should be used when we wan't to access the mount on the filesystem.
In next patches we want to be able to change the location of the mount on
restore in service mount namespace, while not changing ->mountpoint string.
All places where we don't want to access the mount but instead want to
determine relations between mounts in the initial mount tree or just print path
should use ns_mountpoint.
This change effectively brings no change of behaviour everything is the same
for now.
Still leave ->mountpoint references for remap, cr_time and initialization which
need to work with exact variable.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/235c761e0
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On dump ->mountpoint and ->ns_mountpoint is the same, but on restore
->mountpoint can be changed by mount tree yard setup and remap (and who
knows what else =) ). It is not good to use ->mountpoint for path
comparison between mounts if we are not explictly need to compare
"changed" paths. Imagine the remap change will make two mounts have
different prefixes in ->mountpoint and we won't be able so understand
that those mounts originally were subpaths.
This patch handles 2 simple cases:
a) These functions called ONLY ON DUMP so for them there is no effective
change: fixup_overlayfs, fusectl_dump, check_one_mark, __lookup_overlayfs,
mount_resolve_path, try_resolve_ext_mount, validate_mounts (first and third),
resolve_external_mounts, get_clean_mnt, __umount_children_overmounts,
__umount_overmounts, ns_open_mountpoint, open_mountpoint, dump_one_fs,
dump_one_mountpoint, clean_cr_time_mounts, collect_unix_bindmounts.
b) In these functions ONLY LOGS changed, so no algorithm change:
always_fail, mnt_build_ids_tree, mnt_tree_show, unsupported_nfs_bindmounts,
unsupported_nfs_mount, unsupported_mount, validate_mounts (second),
__search_bindmounts, resolve_shared_mounts, mnt_tree_for_each, resolve_source,
propagate_siblings, propagate_mount, do_mount_one, get_mp_root,
collect_mnt_from_image, merge_mount_trees, ns_remount_writable,
__remount_readonly_mounts, parse_mountinfo.
All complex cases are handled in separate patches.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/4972888dd
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Function mnt_depth is only used on real mounts when building mount tree for
single namespace, thats why we can compare those mounts with ns_mountpoint
safely.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/2be0ff276
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
At this point ns_mountpoint is equal to mountpoint.
More over let's use robust is_same_path helper in should_skip_mount so
that we don't need to rely on ->mountpoint + 1 hacks.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/d4c4271a0
Changes: use is_same_path helper.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previous code did:
1) get rpath: mount's mountpoint relative to it's parent mountpoint
2) get cut_root: parent's root relative to parent's slave root or vice
versa (will be "-" if parents root is wider of "+" if thicker)
3) return parent's slave mountpoint +/- cut_root + rpath
It can be done more robust with get_relative_path:
1) get rpath: mount's mountpoint relative to it's parent mountpoint
2) get fsrpath: add rpath to parent's root (path relative to fs root)
3) get rpath: fsrpath relative to parent's slave root
4) return parent's slave mountpoint + rpath
In the latter approach we do not need to open code workarounds for
consequent slashes in paths (get_relative_path would do this for us),
and we also do not need to have complex logic with +/-.
While on it let's also switch ->mountpoint to ->ns_mountpoint where
possible, as mountpoint can have unexpected prefixes.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/0fd09f8571
Changes: rework mnt_get_sibling_path more.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We need to skip root_yard_mp parent as it has no ns_mountpoint, it also
has no children overmounts so we are safe, all others can be compared by
ns_mountpoints.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e5665c976
Changes: add mi->parent pre-check, reword commit message.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Fail root_path_from_parent if parent is root_yard, we want to only
lookup root path in real parent mounts.
Now it is safe to use ns_mountpoint instead of mountpoint as both
children and parent have it and they are relative.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e58a91883
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Function validate_children_collision is both called on dump and on
restore. On dump mountpoint and ns_mountpoint are the same. On restore
as we never call validate_children_collision on helper mounts
(root_yard_mp and cr_time are not in mntinfo list), for all other mounts
strcmp results would be the same with mountpoint and ns_mountpoint.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/8f4fda5ac
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
There is no point of remaping ns root mounts they can't overmount anybody.
This also allows us to switch mnt_needs_remap from ->mountpoint to
->ns_mountpoint for mount comparison in overmount detection.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/9475bf843
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Let's use ->ns_mountpoint in comparison as ->mountpoint can change (e.g.
see how we add ns root in get_mp_mountpoint and in do_remap_mount we can
change it again). We plan to get rid of ->mountpoint everywhere where we
can use unchanged ->ns_mountpoint.
Cherry-picked hunks from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e98e1456d
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Replace ->mountpoint with ->ns_mountpoint for determining relations
between mounts.
Also let's use get_relative_path in autofs_create_dentries as it is more
robust, before that we've missed the case where mountpoint of child of
autofs mount is multilevel subdirectory of parent mountpoint, and always
created them as single level subdirectory.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/5d5462202
Changes: skip children overmount as it does not need a subdirectory.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Put remounted_rw to it. This allows us to easily add some more of such
variables without allocating each one of them separately.
Due to existance of shfree_last shmalloc'ed region can be inherited from
the previous caller so it needs to be explicitly zero initialized.
Fixes: 0a2d380e6 ("ghost/mount: allocate remounted_rw in shmem to get
info from other processes")
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/6750e5793
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Expression (x && REMOUNTED_RW) is always same as just (x).
It should've been (x & REMOUNTED_RW) to check if mount is marked as
temporary remounted writable and requires to be switched back.
By fixing this check we eliminate excess readonly remounts.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/167f8ac67
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Let's merge mount trees under root_yard just after reading from image.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/8e8ecdfdc
Changes: split only root yard part as a separate patch, and put root
yard alloc into merge_mount_trees.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Function mnt_is_overmounted is designed to detect if mount is overmounted in
current tree using comparison of mountpoints of neighbour mounts for detection.
We want to get actual overmounts in dumped tree, we don't expect that helper
mounts we add or merging will introduce new overmounts. So let's do overmount
detection earlier before adding helpers.
Set is_overmounted = false for root yard and binfmt helper mounts.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e98e1456d
Changes: rename set_is_overmounted to prepare_is_overmounted, move it
just after collecting mounts from images to mount tree, handle helper
mounts.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Will use it to find shared mount we can bind from and also can inherit
external slavery. Device-external can't give us external slavery.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/dcd952c4c
Changes: switch to mnt_bind_pick helper.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
There is no point to lose this information, having -1 everywhere in
mount images instead of acutall master id can be confusing.
Note that now need_master is true for bindmounts of root mounts with
same master_id as root mount, so now they are handled with a common
code, we've added can_receive_master_from_root check specially to handle
this case right. Also note that in propagate_mount we no more set ->bind
for this case, this is handled by mnt_ext_slave list related code.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/b3c9dc05e
Stripped only master_id relative part of original patch, add
preparational patches before this one.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We need to put mounts which need to inherit master_id from external
mounts or from root mount into separate list, so that we can set ->bind
on them right in propagate_siblings.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/ea592cf6e
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If mount has external master_id it can inherit it as a bind of external
mount, but also it can inherit it as a bind of container root mount, so
let's add similar condition to allow such mounts.
Note: need_master is false for binds of root mount which can inherit
master_id from root mounts yet, this would change in next patch.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Root yard mount also has mnt_id == 0 so it will look better with a new
name. Let's explicitly initialize root yard mnt_id to HELPER_MNT_ID
for the sake of code readability.
Also in near future we might want to create additional mount helpers to support
mounts in CT with no fsroot mounted.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/45bf6f0ee
Changes: split umount hunk to previous patch, set HELPER_MNT_ID for root
yard.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On dump, yes, mountpoint and ns_mountpoint are the same, but on restore
they don't and puting something like "<root_yard>/binfmt_misc" to
ns_mountpoint is wrong, let's leave ns_mountpoint NULL, this mount
should not be compared by ns_mountpoint with other mounts anyway.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Put our auxiliary binfmt_misc mount in "<root_yard>/binfmt_misc" instead
of "<root_yard>/<mntns>/proc/sys/fs/binfmt_misc". Thus we can restore
binfmt_misc without altering actual mount tree, which looks much more
safe.
For that we need to remove "fake top mount_info" handling from
add_cr_time_mount as now we intentionally add binfmt_misc mount as a
child of ("fake") root yard. On dump this does not change anything.
Also we need to create mountpoint for binfmt_misc in root yard.
As now mount is out of restored mount tree we don't need to umount it,
so remove corresponding CRTIME_MNT_ID umount hunk in do_new_mount.
Note: to make binfmt_misc c/r work criu should be compiled with
CONFIG_BINFMT_MISC_VIRTUALIZED and binfmt_misc should be actually
virtualized and this is only done in Virtuozzo kernel per ve.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/2eb535843
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/d79c7f441
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/34002bef4
Cherry-picked one hunk from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/45bf6f0ee
Changes: merge all fixups together to one consistent patch.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Before this change we didn't apply sb-flags if we mount the root mount of
non-root mntns. There is no point in it, if we got to do_new_mount this root
mount is not external bind, so we won't change sb-flags on host if we change it
for this mount. So we just loose sb-flags on some regular container mount for
no reason. Fix it.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e7ffe4c60
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This creates nested mntns and does pivot_root to tmpfs mount, so that
roots of original test mntns and in nested mntns are different.
Before allowing nested mntnses with different roots in previous patch
this would fail.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Only root in root-mntns is special (see rst_mnt_is_root) all other
mounts are mounted regulary there is no difference between ns root and
any other mount or bind-mount.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/f41e41dd5
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Helper mnt_is_root_bind indicates that mount can be bind-mounted from
the root mount (which in it's turn from opts.root).
Use it in validate_mounts: we should skip unsupported mount from fsroot check
if we know it will be bindmounted from root mount, is_ns_root check was wrong.
Also fix root mount check in dump_one_fs, root mounts in non root mntns should
be dumped normally if they are not bind-mounts of root mount.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/25d078971
Changes: switch to mnt_bind_pick helper, export to mount.h, also add
mnt_get_root_bind helper for future use in mount-v2, remove excess root
yard hunk.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This test creates two mount namespaces, one "root" with external mount
at /mnt_ext_collision.test/dst and one "nested" with different internal
mount at /mnt_ext_collision.test/dst instead.
This case is important for nested containers, if we dump a container
with some external mount in /mnt we should not also replace mounts in
/mnt for nested containers with the external one. (One example is docker
containers inside Virtuozzo containers.)
Without previous patch which restricts external mounts resolution to
only root mntns of container this test fails as internal mount is
replaced by external one after migration.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We resolve mountpoint-external mounts on dump by mountpoint comparison,
so if we have other mount (other superblock e.g. in nested mntns) with
same mountpoint we would also resolve this mount as external and restore
it as external: replacing it completely with different mount... That's
wrong, so to make this interface more robust let's only resolve
mountpoint-external mounts in root mntns of container, not in all
mntnses as it was before.
Note: if actual external mount (bind of external) gets to nested mntns
it's ok not to resolve it as external as criu would bind it from the
resolved mount in root mntns. So external mounts in nested mntns are
still supported after this patch.
Cherry-picked one hunk from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/034498b28
Changes: apply mntns check only to mountpoint-external mounts.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This test simply creates a) root external mount and b) "deeper"
bindmount for it (deeper in terms of mnt_depth). Our mount restore code
tries to mount (b) first and fails (without previous patch ordering
external mounts before their binds).
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/d31954669
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The problem when we don't order these mounts we can get to mounting
non-external bind first via do_new_mount and fail c/r. For instance for
tmpfs we would fail on no image to get contents from. See the test
mnt_ext_root for more info.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/baf3f8db8
Changes: switch to mnt_bind_pick helper, export to mount.h, make check
in can_mount_now skip mounts with ->bind set.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Function dump_one_fs already has mnt_is_external_bind check inside, so
there is no point to check pm->external one more time.
Function check_bindmount is intended to check devpts bindmount's master
was opened in right mount namespace, but if bindmount is external mount
there is no point to check this. Let's also skip check for bindmounts of
external mounts.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We use mnt_is_external():
1) In validate_mounts() to skip fsroot existence check for mounts which
will be bind-mounted from external mounts.
2) In resolve_shared_mounts() to skip error on slave mounts without
master mount, if they can receive these master_id through external
mount.
3) In dump_one_fs to skip dump of mounts which will be bind-mounted from
external mounts.
Cases (1) and (3) are the same, but case (2) is quiet different. Lets
split these cases thus making things simplier.
Effectively these patch does not change criu's behaviour at all. While
I can't say that old mnt_is_external was wrong, it was too complex and
hard for understanding, so it's worth to switch to lookup across
bindmounts list via general mnt_bind_pick() helper. And now when it is
obvious that mnt_is_external looks for external bindmount, let's also
change it's name to mnt_is_external_bind.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/494b52ba8
Changes: use mnt_bind_pick helper, use is_sub_path helper to be more
robust, rename mnt_is_external to mnt_is_external_bind, fix
clang-format, export to mount.h, use mnt_is_nodev_external as we can not
inherit master from device-external mounts.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Adding different pick functions we would be able to search different
things like mounted bind with wider root, or external bind, or external
bind with same sharing group and so on and so forth.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is a smart way of getting relative paths:
1) Always returns relative path, no unexpected starting '/';
2) Detects subpath even if path formats are different, only real directory
and file names matter;
3) No path modiffication/allocation, returns shifted pointer to the
orignal path.
We have many places where we need to cut subpath from path. Different code
blocks doing this job spread widely across the codebase for instance see:
cut_root_for_bind and root_path_from_parent. But those implementations rely on
the fact that subpath's and path's formats are the same.
When we modify or concatenate paths we can accidentally get strange
path formats, paths given by user can have strange format, and the job
to manually maintain all paths in "simple" format everywhere is too
hard. So let's just add a tool to compare "strange" paths.
E.g.:
get_relative_path("./a////.///./b//././c", "///./a/b") == "c"
Note: ".." in path is not supported, and we just can't support it right
without full filesystem tree information to resolve paths like
"../../a", so we just treat ".." as a directory name which should work
in simple cases.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/73a771348
Changes: add other useful robust path comparison helpers is_sub_path and
is_same_path based on get_relative_path, fix clang-format.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Before this patch mnt_is_external() used non-populated mnt_bind list
when called from resolve_shared_mounts(), thus it could work not as
intended.
Let's add separate helper search_bindmounts() for populating mnt_bind
list, and add mnt_bind_is_populated to differentiate between
non-populated list and just empty populated list. This way we can add a
BUG_ON to mnt_is_external to catch such order problems in future.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/e464c1c6d
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/8b22b30d5
Cherry-picked one hunk from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/ca9de41e3
Changes: simplify commit message, merge fixups: search bindmounts
earlier so that we have bindmounts info as early as possible, rename
mnt_no_bind to mnt_bind_is_populated and simplify it's logic a bit.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Fstype and source fields can be changed by resolve_external_mounts() or
by try_resolve_ext_mount() for external mounts, but we can have other
mounts from same superblock which are not detected as external, for
instance bind of subdirectory from device-external or bind of
mountpoint-external mount to other mountpoint. So we need to still be
able to find bindmounts between mounts with changed fstype or source and
unchanged mounts.
So let's make fstype/source checks in mounts_sb_equal ignored for
external mounts. Leave only fstype->sb_equal checks if have them.
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/fadc38d84
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/f9700cb12
Changes: merge two commits in one and rework, remove ":)", reword
commit-message to make patch self-sufficient.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previously only autodetected and mountpoint external mounts had
mount_info->external field set, let's fix this injustice so that we can
operate all external mounts in a similar manner.
Also:
Print info message when device external mount is detected similar to
mountpoint external mounts detection.
Add helper mnt_is_nodev_external to let do_mount_one, can_mount_now and
do_bind_mount handle device external mounts separately as it was before.
Handle device external mount right in get_mp_root to set ->external on
restore. (note: calling ext_mount_lookup is only meaningfull for
mountpoint external mounts)
Add helper mnt_is_dev_external to use in resolve_source to make it more
clear that it is a device external mount restore path.
All other "if (mi->external)" checks now also handle device external
mounts, but they all look safe to do so and could've done it initially,
here is a list: fusectl_dump, mnt_is_external, dump_one_mountpoint,
propagate_mount.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/afd899539
Changes: cleanup commit message, add some helpers.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Device-external mounts are restored via do_new_mount(), but function
do_new_mount only allows creating mounts with root "/", as it does
simple mount (not bind) without any later root change. Restoring
non-root mounts via do_new_mount is just imposible.
So let's detect mounts as device-external only when they have fsroot
root, all other non-fsroot binds of this device would be restored as
bindmounts of fsroot ones.
This is a cosmetic change as though non-root mounts were detected as
device-external before this patch they anyway would not be created with
do_new_mount() because of fsroot/bind check in can_mount_now orders them
to be restored as binds.
Cherry-picked one hunk from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/afd899539
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Use this helper everywhere instead of manually adding mounts to the head
of the list, this way it is much easier to track all places where we do
add to mntinfo list.
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/7bca9397b
Changes: skip hunk adding root_yard_mp to the list because root yard has
not fully initialized mountinfo structure (can break code which uses
mntinfo fallback in lookup_nsid_by_mnt_id), let's only have real mounts
in mntinfo list. Also skip cr_time mount from mntinfo list for the same
reason.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Before these change the on-host-"zdtm_auto_ext_mnt" mount with
mountpoint "/tmp/zdtm_ext_auto.XXXXXX" was private/shared depending on
it's parent mount "/tmp". And e.g. on my setup the parent mount on
"/tmp" is private and our "host" mount becomes private too. So
in-container-"zdtm_auto_ext_mnt" external mount is also private but test
name hints it should be slave.
E.g. If I ran mnt_ext_master before this patch, in mnt_ext_master
process mntns we see that our "external" mount is private but not slave:
[root@fedora criu]# grep zdtm_auto_ext_mnt /proc/167077/mountinfo
1239 1238 0:138 /test /ext_mounts rw,relatime - tmpfs zdtm_auto_ext_mnt rw,seclabel,inode64
After this patch:
[root@fedora criu]# grep zdtm_auto_ext_mnt /proc/166385/mountinfo
1239 1238 0:138 /test /ext_mounts rw,relatime master:413 - tmpfs zdtm_auto_ext_mnt rw,seclabel,inode64
^^^^^^^^^^
So we just explicitly make on-host-"zdtm_auto_ext_mnt" shared, and this
makes in-container-"zdtm_auto_ext_mnt" external mount slave.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/a1a221fe9
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
coverity CID 389197:
CID 389197 (#1 of 1): Invalid printf format string (PRINTF_ARGS)
format_error: Length modifier L not applicable to conversion specifier in %Lu. [show details]
284 pr_err("Incompatible uffd API: expected %Lu, got %Lu\n", UFFD_API, uffdio_api.api);
Looking on C11 standard it seems that "%Lu" is undefined, we better not
use this, see:
"L Specifies that a following a, A, e, E, f, F, g, or G conversion
specifier applies to a long double argument."
http://port70.net/~nsz/c/c11/n1570.html#7.21.6.1p7
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
coverity CID 389191:
int unix_sk_id_add(unsigned int ino)
2327{
2328 char *e_str;
2329
1. alloc_fn: Storage is returned from allocation function malloc.
2. var_assign: Assigning: ___p = storage returned from malloc(20UL).
3. Condition !___p, taking false branch.
4. leaked_storage: Variable ___p going out of scope leaks the storage it points to.
5. var_assign: Assigning: e_str = ({...; ___p;}).
2330 e_str = xmalloc(20);
6. Condition !e_str, taking false branch.
2331 if (!e_str)
2332 return -1;
7. noescape: Resource e_str is not freed or pointed-to in snprintf.
2333 snprintf(e_str, 20, "unix[%u]", ino);
8. noescape: Resource e_str is not freed or pointed-to in add_external. [show details]
CID 389191 (#1 of 1): Resource leak (RESOURCE_LEAK)9. leaked_storage: Variable e_str going out of scope leaks the storage it points to.
2334 return add_external(e_str);
2335}
We should free e_str string after we finish it's use in unix_sk_id_add,
easiest way to do it is to use cleanup_free attribute.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Modifications to support criu image streamer when using amdgpu_plugin.
When running with criu image streamer, fseek/lseek is not available so
we store the file size in the first 8-bytes of the actual file.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Store BO contents directly to file (1 per GPU) instead of using
protobuf.
Bug Fix:
Fixes an issue where we could not handle BOs bigger than 4GB because
protobuf has an internal limit of 4GB for the Bytes structure.
Performance Improvements:
This significantly reduces CR duration on multi-GPU systems as it allows
reading and writing to disk in parallel. During checkpoint, instead of
waiting for all the BO contents to be read from the one protobuf file,
we can now start writing the BO contents as soon as the first BO is read
from disk. During restore, we can start writing BO contents to disk
after the first BO from VRAM. This also reduces the peak amount of
system memory used as we only need to keep 1 BO content in memory per
GPU at a time instead of all the BO contents.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
This sets up the pytorch environment for BERT Transformers and also sets
up CRIU along with all its dependencies including amdgpu plugin for
supporting CR with AMDGPUs.
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
On newer kernel's (> 5.13), KFD & DRM drivers will only allow the
/dev/renderD* file descriptors that were used during the CRIU_RESTORE
ioctl when calling mmap for the vma's.
During restore, after opening /dev/renderD*, amdgpu_plugin keeps the
FDs opened and instead returns a copy of the FDs to CRIU. The same FDs
are then returned during the UPDATE_VMAMAP hooks so that they can be
used by CRIU to call mmap. Duplicated FDs created using dup are
references to the same struct file inside the kernel so they are also
allowed to mmap.
To prevent the opened FDs inside amdgpu_plugin from conflicting with
FDs used by the target restore application, we make sure that the
lowest-numbered FD that amdgpu_plugin will use is greater than the
highest-numbered FD that is used by the target application.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
AMD Radeon GPUs have special sDMA (system dma engines) IPs that can be
used to speed up the read write operations from the VRAM and GTT memory.
Depends on:
* The kernel mode driver (kfd) creating the dmabuf objects for the kfd
BOs in both checkpoint and restore operation.
* libdrm and libdrm_amdgpu libraries
Suggested-by: Felix Kuehling <felix.kuehling@amd.com>
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Libhsakmt(thunk) uses a shared memory file in /dev/shm/hsakmt_shared_mem
and its semaphore in /dev/shm/hsakmt_shared_mem. Adding a check during
checkpoint to see if these two files exist. If they exist then the
plugin will try to restore them during restore.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Implement multi-threaded code to read and write contents of each GPU
VRAM BOs in parallel in order to speed up dumping process when using
multiple GPUs.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Adding unit tests for GPU remapping code when checkpointing and
restoring on different nodes with different topologies.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Add optional parameters to override default behavior during restore.
These parameters are passed in as environment variables before executing
CRIU.
List of parameters:
KFD_FW_VER_CHECK - disable firmware version check
KFD_SDMA_FW_VER_CHECK - disable SDMA firmware version check
KFD_CACHES_COUNT_CHECK - disable caches count check
KFD_NUM_GWS_CHECK - disable num_gws check
KFD_VRAM_SIZE_CHECK - disable VRAM size check
KFD_NUMA_CHECK - preserve NUMA regions
KFD_CAPABILITY_CHECK - disable capability check
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
The device topology on the restore node can be different from the
topology on the checkpointed node. The GPUs on the restore node may
have different gpu_ids, minor number. or some GPUs may have different
properties as checkpointed node. During restore, the CRIU plugin
determines the target GPUs to avoid restore failures caused by trying
to restore a process on a gpu that is different.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Parse local system topology in /sys/class/kfd/kfd/topology/nodes/ and
store properties for each gpu in the CRIU image files. The gpu
properties can then be used later during restore to make the process is
restored on gpu's with similar properties.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
To support Checkpoint Restore with AMDGPUs for ROCm workloads, introduce
a new plugin to assist CRIU with the help of AMD KFD kernel driver. This
initial commit just provides the basic framework to build up further
capabilities. Like CRIU, the amdgpu plugin also uses protobuf to
serialize
and save the amdkfd data which is mostly VRAM contents with some
metadata.
We generate a data file "amdgpu-kfd-<id>.img" during the dump stage. On restore
this file is read and extracted to re-create various types of buffer
objects that belonged to the previously checkpointed process. Upon
restore the mmap page offset within a device file might change so we use
the new hook to update and adjust the mmap offsets for newly created
target process. This is needed for sys_mmap call in pie restorer phase.
Support for queues and events is added in future patches of this series.
With the current implementation (amdgpu_plugin), we support:
- Only compute workloads such (Non Gfx) are supported
- GPU visible inside a container
- AMD GPU Gfx 9 Family
- Pytorch Benchmarks such as BERT Base
amdgpu plugin dependes on libdrm and libdrm_amdgpu which are typically
installed with libdrm-dev package. We build amdgpu_plugin only when the
dependencies are met on the target system and when user intends to
install the amdgpu plugin and not by default with criu build.
Suggested-by: Felix Kuehling <felix.kuehling@amd.com>
Co-authored-by: David Yat Sin <david.yatsin@amd.com>
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
kfd_ioctl.h contains the definitions for the APIs and required arguments
to call the ioctls so simply copy the header as is for amdgpu plugin.
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
During premap phase, skip vmas that are handled by external plugins as
their offsets may change when the plugin restores them. This change is
needed when running with criu image streamer.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Adding a dedicated flag for vma's that are handled by an external plugin
as previously used VMA_UNSUPP flag depends on vma not having
VMA_FILE_SHARED flag.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Add a new global function to return unused FD based on the pid. This
function can be used in situations where we need a FD that will not
conflict with FDs used by target restore process, but
struct pstree_item is not available (e.g plugins)
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
Some device drivers (e.g DRM) only allow the file descriptor that was
used to create the vma to be used when calling mmap.
In this case, instead of opening a new FD, the plugin will return a
valid FD that can be used for mmap later. The plugin needs to close the
returned FD later. Copies of the returned FD that are created using dup
or fnctl(..,F_DUPFD,..) are references to the same struct file inside
kernel so they are also allowed to mmap.
The plugin does not need to update the path anymore as the plugin can
return a FD for the correct path.
Signed-off-by: David Yat Sin <david.yatsin@amd.com>
coverity CID 389187:
3193int veth_pair_add(char *in, char *out)
3194{
3195 char *e_str;
3196
1. alloc_fn: Storage is returned from allocation function malloc.
2. var_assign: Assigning: ___p = storage returned from malloc(200UL).
3. Condition !___p, taking false branch.
4. leaked_storage: Variable ___p going out of scope leaks the storage it points to.
5. var_assign: Assigning: e_str = ({...; ___p;}).
3197 e_str = xmalloc(200); /* For 3 IFNAMSIZ + 8 service characters */
6. Condition !e_str, taking false branch.
3198 if (!e_str)
3199 return -1;
7. noescape: Resource e_str is not freed or pointed-to in snprintf.
3200 snprintf(e_str, 200, "veth[%s]:%s", in, out);
8. noescape: Resource e_str is not freed or pointed-to in add_external. [show details]
CID 389187 (#1 of 1): Resource leak (RESOURCE_LEAK)9. leaked_storage: Variable e_str going out of scope leaks the storage it points to.
3201 return add_external(e_str);
3202}
We should free e_str string after we finish it's use in veth_pair_add,
easiest way to do it is to use cleanup_free attribute.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
coverity CID 389192:
550static int parse_join_ns(const char *ptr)
551{
...
553 char *ns;
554
1. alloc_fn: Storage is returned from allocation function strdup.
2. var_assign: Assigning: ___p = storage returned from strdup(ptr).
3. Condition !___p, taking false branch.
4. leaked_storage: Variable ___p going out of scope leaks the storage it points to.
5. var_assign: Assigning: ns = ({...; ___p;}).
555 ns = xstrdup(ptr);
6. Condition ns == NULL, taking false branch.
556 if (ns == NULL)
557 return -1;
558
7. noescape: Resource ns is not freed or pointed-to in strchr.
559 aux = strchr(ns, ':');
8. Condition aux == NULL, taking true branch.
560 if (aux == NULL)
CID 389192 (#1 of 1): Resource leak (RESOURCE_LEAK)9. leaked_storage: Variable ns going out of scope leaks the storage it points to.
561 return -1;
We should free ns string after we finish it's use in parse_join_ns,
easiest way to do it is to use cleanup_free attribute.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The config_inotify_irmap test duplicates inotify_irmap with slight
change to add the --force-irmap and --irmap-scan-path options in
a configuration file.
The --criu-config option of ZDTM provides more general solution
for testing CRIU options provided in configuration files.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The --criu-config option allows to run test with CRIU options provided
via configuration files instead of command-line arguments.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Using long-form command-line options would allows us to provide
them via config file to CRIU.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This patch improves the readability of zdtm by refactoring the top-level
code into a main function.
https://docs.python.org/3/library/__main__.html
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
coverity CID 389193:
CID 389193 (#1 of 1): Printf format string issue (PW.BAD_PRINTF_FORMAT_STRING)
1. bad_printf_format_string: invalid format string conversion
598 pr_warn("Can't stat socket %#x(%s), skipping: %m (err %d)\n", id, rpath, errno);
Specifier "%#x" is wrong for id as it is of type uint32_t, let's change
it to "%#" PRIx32 "" to fix the problem.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
coverity CID 389205:
452int dump_tun_link(NetDeviceEntry *nde, struct cr_imgset *fds, struct nlattr **info)
453{
...
458 struct tun_link *tl;
...
2. alloc_fn: Storage is returned from allocation function get_tun_link_fd. [show details]
3. var_assign: Assigning: tl = storage returned from get_tun_link_fd(nde->name, nde->peer_nsid, tle.flags).
475 tl = get_tun_link_fd(nde->name, nde->peer_nsid, tle.flags);
4. Condition !tl, taking false branch.
476 if (!tl)
477 return ret;
478
479 tle.vnethdr = tl->dmp.vnethdr;
480 tle.sndbuf = tl->dmp.sndbuf;
481
482 nde->tun = &tle;
CID 389205 (#1 of 1): Resource leak (RESOURCE_LEAK)5. leaked_storage: Variable tl going out of scope leaks the storage it points to.
483 return write_netdev_img(nde, fds, info);
484}
Function get_tun_link_fd() can both return tun_link entry from tun_links
list and a newly allocated one. So we should not free entry if it is
from list and should free it when it is a new one to fix leak.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
coverity CID 389202:
54int ext_mount_add(char *key, char *val)
55{
56 char *e_str;
57
1. alloc_fn: Storage is returned from allocation function malloc.
2. var_assign: Assigning: ___p = storage returned from malloc(strlen(key) + strlen(val) + 8UL).
3. Condition !___p, taking false branch.
4. leaked_storage: Variable ___p going out of scope leaks the storage it points to.
5. var_assign: Assigning: e_str = ({...; ___p;}).
58 e_str = xmalloc(strlen(key) + strlen(val) + 8);
6. Condition !e_str, taking false branch.
59 if (!e_str)
60 return -1;
...
7. noescape: Resource e_str is not freed or pointed-to in sprintf.
73 sprintf(e_str, "mnt[%s]:%s", key, val);
8. noescape: Resource e_str is not freed or pointed-to in add_external. [show details]
CID 389202 (#1 of 1): Resource leak (RESOURCE_LEAK)9. leaked_storage: Variable e_str going out of scope leaks the storage it points to.
74 return add_external(e_str);
75}
We need to free e_str after add_external used it.
v2: use cleanup_free attribute (@adrianreber)
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
During error injection tests there are random values loaded in some of
the registers. The kernel, however, has the following check:
if (mxcsr[0] & ~mxcsr_feature_mask)
return -EINVAL;
So depending on the random values loaded mxcsr might have values that
the kernel rejects with EINVAL. Setting mxcsr to zero during the tests
lets the error injection test pass.
Signed-off-by: Adrian Reber <areber@redhat.com>
There is no 'err' argument for print(), it should be in grep_errors() in
line below.
Fixes: bed670f62 ("zdtm: print tails of all logs if a test has failed")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Linux Kernel release 5.16 removed support for LOCK_MAND flock and so the
test to verify if LOCK_MAND works started to fail with 5.16.
The kernel also logs following message:
Attempt to set a LOCK_MAND lock via flock(2). This support has been removed and the request ignored.
This fixes CRIU CI using Fedora with 5.16.
See Linux Kernel commit 90f7d7a0d0d68623b5f7df5621a8d54d9518fcc4
"locks: remove LOCK_MAND flock lock support"
Signed-off-by: Adrian Reber <areber@redhat.com>
Starting with Linux Kernel release 5.16 the fdinfo proc entry contains
a map_extra field which breaks CRIU parsing of bpfmap entries.
This commit adds the map_extra as a possible field to CRIU. The value of
map_extra is not passed to the kernel on restore as it does not seem to
be evaluated in the code paths CRIU restore is using for BPF.
This fixes CRIU CI using Fedora with 5.16.
See Linux commit 9330986c03006ab1d33d243b7cfe598a7a3c1baa
"bpf: Add bloom filter map implementation"
Signed-off-by: Adrian Reber <areber@redhat.com>
Currently, hugetlb mappings is not premapped so in the restore content phase, we
skip page read these pages, enqueue the iovec for later reading in restorer and
eventually close the page read. However, image-streamer expects the whole image
to be read and the image is not re-opened, sent twice. These MAP_HUGETLB test
cases will result in EPIPE error. Temporarily disable these test cases for now.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
This commit add a test for checkpoint/restore MAP_HUGETLB memory mappings.
A new zdtm helper get_mapping_dev() is added to get the device number of
the memory mapping.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
As hugetlb mappings are not premapped, they are not registered to uffd service
in restorer code. We must not mark these mappings as PPB_LAZY in generate_iovs()
otherwise when restoring content of these mappings, we will keep looking for in
uffd and get ENOENT because they are not registered.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
As we cannot use mremap() to move the hugetlb mapping around until Linux kernel
version 5.16, we need to skip premapping hugetlb mapping.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
When memfd can be used with hugetlb, we use memfd for checkpoint/restore
anonymous shared memory. Otherwise, map_files symlinks is used for
checkpoint/restore anonymous shared memory.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Attach the System V shared memory segments to the address space via shmat() to
determine if they are backed by hugetlb and their page size. Use these
information for setting the correct flags on restore.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
These numbers are used to determine whether a memory mapping is backed by
hugetlb and its page size.
As the hugepage can be allocated more after the first time we collect kerndat,
we need to collect the missing device numbers every time we load the kerndat
cache.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
When PTRACE_GET_THREAD_AREA errors on kernels with
!CONFIG_IA32_EMULATION beacuse of missing support (-EIO), compel should
ignore uch errors in native mode.
However the check for error type uses return value of ptrace rather than
errno, which will always result in error propagation.
Use errno to detect type of error to fix this.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
As we call mmap syscall directly, the returned value in error case is the error
number not -1 like in libc wrapper. Use IS_ERR for correct checking in error
case.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
os.WEXITSTATUS() returns the process exit status and it should be used
only if WIFEXITED() is true, i.e., the process terminated normally.
os.waitstatus_to_exitcode() does the same as os.WEXITSTATUS() but it
also handles the case when the process has been terminated by a signal.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
If we replace old_sid with current_sid we should also do same
replacement for matching pgid (=old_sid).
Reported in CRIU gitter by Younes Manton (@ymanton)
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
autofs.c:66:17: error: pointer 'str' may be used after 'realloc' [-Werror=use-after-free]
autofs.c: In function 'check_automount':
../lib/zdtmtst.h:131:9: error: pointer 'mountpoint' may be used after 'free' [-Werror=use-after-free]
131 | test_msg("ERR: %s:%d: " format " (errno = %d (%s))\n", __FILE__, __LINE__, ##arg, errno, strerror(errno))
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
autofs.c:277:17: note: in expansion of macro 'pr_perror'
277 | pr_perror("%s: failed to close fd %d", mountpoint, p->fd);
| ^~~~~~~~~
autofs.c:268:9: note: call to 'free' here
268 | free(mountpoint);
| ^~~~~~~~~~~~~~~~
Fixes: #1731
v2: (@Snorch) always update `str` after successful realloc()
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Running cross compile tests with Debian unstable sometimes
fails due to missing or outdated packages.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Parasite creation started to fail with GCC 12:
On x86_64 with:
./compel/compel-host hgen -f criu/pie/restorer.built-in.o -o criu/pie/restorer-blob.h
Error (compel/src/lib/handle-elf-host.c:337): Unexpected undefined symbol: `strlen'. External symbol in PIE?
On aarch64 with:
ld: criu/pie/restorer.o: in function `lsm_set_label':
/drone/src/criu/pie/restorer.c:174: undefined reference to `strlen'
Line 174 is: "for (len = 0; label[len]; len++)"
Adding '-ffreestanding' to parasite compilation fixes these errors
because, according to GCC developers:
"strlen is a standard C function, so I don't see any bug in that being used
unless you do a freestanding compilation (-nostdlib isn't that)."
Signed-off-by: Adrian Reber <areber@redhat.com>
This fixes:
criu/config.c: In function ‘parse_statement’:
criu/config.c:232:43: error: the comparison will always evaluate as ‘true’ for the pointer operand in ‘*(configuration + (sizetype)((long unsigned int)i * 8)) + ((sizetype)offset + 1)’ must not be NULL [-Werror=address]
232 | if (configuration[i] + offset + 1 != 0 && strchr(configuration[i] + offset, ' ')) {
| ^~
Signed-off-by: Adrian Reber <areber@redhat.com>
This is a confusing change as it seems the original code was just wrong.
GCC 12 complains with:
In function ‘__conv_val’,
inlined from ‘std_strtoul’ at compel/plugins/std/string.c:202:7:
compel/plugins/std/string.c:154:24: error: array subscript 97 is above array bounds of ‘const char[37]’ [-Werror=array-bounds]
154 | return &conv_tab[__tolower(c)] - conv_tab;
| ^~~~~~~~~~~~~~~~~~~~~~~
compel/plugins/std/string.c: In function ‘std_strtoul’:
compel/plugins/std/string.c:10:19: note: while referencing ‘conv_tab’
10 | static const char conv_tab[] = "0123456789abcdefghijklmnopqrstuvwxyz";
| ^~~~~~~~
cc1: all warnings being treated as errors
Which sounds correct. The array conv_tab has just 37 elements.
If I understand the code correctly we are trying to convert anything
that is character between a-z and A-Z to a number for cases where
the base is larger than 10. For a base 11 conversion b|B should return 11.
For a base 35 conversion z|Z should return 35. This is all for a strtoul()
implementation.
The original code was:
static const char conv_tab[] = "0123456789abcdefghijklmnopqrstuvwxyz";
return &conv_tab[__tolower(c)] - conv_tab;
and that seems wrong. If conv_tab would have been some kind of hash it could
have worked, but '__tolower()' will always return something larger than
97 ('a') which will always overflow the array.
But maybe I just don't get that part of the code.
I replaced it with
return __tolower(c) - 'a' + 10;
which does the right thing: 'A' = 10, 'B' = 11 ... 'Z' = 35
Signed-off-by: Adrian Reber <areber@redhat.com>
This case sometimes will cause SIGILL signal in arm64 platform.
<<ARM Coretex-A series Programmer's Guide for ARMv8-A>> notes:
The ARM architecture does not require the hardware to ensure coherency
between instruction caches and memory, even for locations of shared
memory.
Therefore, we need flush dcache and icache for self-modifying code.
- https://developer.arm.com/documentation/den0024/a/Caches/Point-of-coherency-and-unification
Signed-off-by: fu.lin <fulin10@huawei.com>
When requested iovs are huge, criu needs to invoke more then one
preadv()s. In this situation criu truncates memory image with
offset of first preadv() and length of last one, which leads
to leakage of memory image. This patch fixs truncating with right
offset and length.
Signed-off-by: Liu Hua <weldonliu@tencent.com>
This commit adds feature check support to libcriu. It already exists in
the CLI and RPC and this just extends it to libcriu.
This commit provides one function to do all possible feature checks in
one call. The parameter to the feature check function is a structure and
the user can enable which features should be checked.
Using a structure makes the function extensible without the need to
break the API/ABI in the future.
Signed-off-by: Adrian Reber <areber@redhat.com>
A couple of months (or years) ago I looked into lgtm.com for CRIU. Today
on a pull request I saw result from lgtm.com for the first time and it
failed. Not sure what triggered the lgtm.com message into the CRIU
repository, but with the .lgtm.yml file in this commit lgtm.com can
actually build CRIU.
Signed-off-by: Adrian Reber <areber@redhat.com>
We face that btrfs returns anonymous device in stat instead of real
superblock dev for volumes, thus all btrfs volume mounts does not pass
check_mountpoint_fd due to dev missmatch between stat and mountinfo. We
can use special helper get_sdev_from_fd instead of stat to try to get
real dev of fd for btrfs.
We move check_mountpoint_fd from open_mountpoint into get_clean_fd and
ns_open_mountpoint to the point where temporary mount we open fd to is
still in mountinfo, thus get_sdev_from_fd would be able to find tmp
mount in mountinfo.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
New get_sdev_from_fd helper first gets mnt_id from fd using fdinfo and
then converts mnt_id to sdev using mountinfo.
By default mnt_id to sdev conversion only works for mounts in mntinfo.
If parse_mountinfo argument is true, will also parse current process
mountinfo when looking for mount sdev, this should be used only with
temporary mounts just created by criu in current mntns.
v3: add argument to parse self mountinfo for auxiliary mounts
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Only place where we used __open_mountpoint with non -1 mnt_fd is
open_mountpoint. Let's use check_mountpoint_fd for this case, so that we
now can remove mnt_id argument. Also now __open_mountpoint actually
always does open.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
GNUTLS_SHUT_RDWR sends an alert containing a close request and waits for
the peer to reply with the same message.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We need to be sure that page-server doesn't wait for a new command when we
call gnutls_bye() that sends an alert containing a close request.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This commit simply makes copies of SOCK_STREAM unix socket tests and uses
SOCK_SEQPACKET instead.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
We have multiple options which are valid only on restore or only on dump
or in any other specific criu mode, so it would be useful to have info
about current mode in opts so that we can validate other options against
current mode.
Plan is to use it for mount-v2 option as it is only valid on restore,
and this would make handling of different types mountpoints much easier.
Realization is a bit different for general code and rpc:
- When criu mode is set from main() we just parse mode from argv[optind]
just after parse_options() found optind of the command. Note that
opts.mode is available before check_options().
- For rpc service we reset opts.mode to CR_SWRK each time we restart
cr_service_work(), in the original service process we still have
CR_SERVICE to differentiate between them, and each request handling
function which does setup_opts_from_req sets opts.mode in accordance
with the processed request type. And it is also available before
check_options().
Now in check_options we can add filters on one mode only options.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Several lines above if (optind >= argc) we go to usage label and fail,
thus we don't need to check (optind < argc) here as it is always true.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Looks like in commit [1] we've non-intentionally added this tmp file to
git, let's remove it.
Fixes: 01ee29702 ("s390:zdtm: Enable zdtm for s390") [1]
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
zdtm_ct.c:44:12: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
44 | static int create_timens()
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
In most cases we run tests as:
./test/zdtm.py run -a
But it's also possible to run tests from root makefile:
make test
In this case, if criu tree have no ./test/umount2 binary
built we get the error like:
make[3]: *** No rule to make target 'umount2'. Stop.
It's worth to mention this "3". That's because we have
build process tree like this:
make -> make -> make -> zdtm.py -> make umount2
and also we have MAKEFLAGS variable set to:
build=-r -R -f ...
And that's bad because "-r" option means no builtin
rules and -R means no builtin variables. That makes
`make umount2` not working. Let's just cleanup this
variable to make things work properly.
Fixes: #1699https://github.com/checkpoint-restore/criu/issues/1699
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
In contrast to the CLI it is not possible to do a single pre-dump via
RPC and thus libcriu. In cr-service.c pre-dump always goes into a
pre-dump loop followed by a final dump. runc already works around this
to only do a single pre-dump by killing the CRIU process waiting for the
message for the final dump.
Trying to implement pre-dump in crun via libcriu it is not as easy to
work around CRIU's pre-dump loop expectations as with runc that directly
talks to CRIU via RPC.
We know that LXC/LXD also does single pre-dumps using the CLI and runc
also only does single pre-dumps by misusing the pre-dump loop interface.
With this commit it is possible to trigger a single pre-dump via RPC and
libcriu without misusing the interface provided via cr-service.c. So
this commit basically updates CRIU to the existing use cases.
The existing pre-dump loop still sounds like a very good idea, but so
far most tools have decided to implement the pre-dump loop themselves.
With this change we can implement pre-dump in crun to match what is
currently implemented in runc.
Signed-off-by: Adrian Reber <areber@redhat.com>
We added cross-compile tests with testing debian release to be able to
replicate the error reported in #1653, however, installing build
dependencies in this release currently fails with the following error:
libc6-dev:armhf : Breaks: libc6-dev-armhf-cross (< 2.33~) but 2.32-1cross4 is to be installed
This is not something we can fix, therefore using the debian unstable
release (instead of testing) could be more reliable option for our CI.
This would still replicate the problem reported in #1653.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The --timeout option was introduced in [1] to prevent criu dump from
being able to hang indefinitely and allow users to adjust the time limit
in seconds for collecting tasks during the dump operation.
[1] d0ff730
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
Fixes: e2e8be37 ("x86/compel/fault-inject: Add a fault-injection for corrupting extended regset")
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Since
e2e8be37 ("x86/compel/fault-inject: Add a fault-injection for corrupting extended regset")
we doing fault-injection test for C/R of threads register set by filling tasks
xsave structures with the garbage. But there are some features for which that's not
safe. It leads to failures like described in #1635
In this particular case we meet the problem with PKRU feature, the problem
that after corrupting pkru registers we may restrict access to some vma areas,
so, after that process with the parasite injected get's segfault and crashes.
Let's manually specify which features is save to fill with the garbage by
keeping proper XFEATURE_MASK_FAULTINJ mask value.
Fixes: e2e8be37 ("x86/compel/fault-inject: Add a fault-injection for corrupting extended regset")
https://github.com/checkpoint-restore/criu/issues/1635
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
We try to disable time namespace based testing for kernels older than
5.11. But we fail to come up with the correct if condition.
This changes (major <= 5) to (major < 5). There are no kernels with
major > 5 so currently the time namespace based are never run. This
should finally change it to run time namespace based tests on kernel
versions newer than 5.10.
Signed-off-by: Adrian Reber <areber@redhat.com>
The version of ps in Alpine image by default is very limited.
It is based on the one from busybox and doesn't support options
such as '-p'.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
Since commit 83301b5367a98 ("af_unix: Set TCP_ESTABLISHED for datagram sockets
too") in Linux kernel, SOCK_DGRAM unix sockets can have TCP_ESTABLISHED state
when connected. So we need to fix checks that assume SOCK_DRAM sockets cannot
have TCP_ESTABLISHED state.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
The function run_tcp_server() was the last place CRIU was still using
the IPv4 only function inet_ntoa(). It was only used during a print, so
that it did not really break anything, but with this commit the output
is now no longer:
Accepted connection from 0.0.0.0:58396
but correctly displaying the IPv6 address
Accepted connection from ::1:58398
if connecting via IPv6.
Signed-off-by: Adrian Reber <areber@redhat.com>
An issue with dumping deleted reg files in overlayfs:
After deleting a file originated from lower layer in merged dir,
fstat() on the /proc/$pid/map_files symlink returns st_nlink=1, while
linkat() fails with errno ENOENT.
Signed-off-by: langyenan <ianlang@tencent.com>
Looking at CI logs there are often messages like:
"[WARNING] Option --keep-going is more useful when running multiple tests"
This commit removes '--keep-going' from single zdtm test runs.
Signed-off-by: Adrian Reber <areber@redhat.com>
Starting with gcc-11, Debian's armhf compiler no longer builds with
a default -mfpu= option. Instead it enables the FPU via an extension
to the -march flag (--with-arch=armv7-a+fp). criu's Makefile explicitly
passes its own -march=armv7-a setting, which overrides the +fp default,
so we end up with no FPU:
cc1: error: '-mfloat-abi=hard': selected architecture lacks an FPU
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
Debian testing has newer compiler version and running
cross compilation tests would allow us to catch any compilation
errors early.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
The current debian stable release is Bullseye, not Buster. However, we
can use the 'stable' release instead. This would allow the CI to
automatically pick up updates in the future.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
When we declare struct and at the same time declare variable pointer of
this struct type, it looks like clang-format threats "*" as a
multiplication operator instead of indirection (pointer declaration)
operator and puts spaces on both sides, which looks wrong.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is a test for "ghost/mount: allocate remounted_rw in shmem to get
info from other processes" patch, without the patch test fails with:
############# Test zdtm/static/mntns_ghost01 FAIL at result check ##############
Test output: ================================
16:15:19.607: 5: ERR: mntns_ghost01.c:95: open for write on rofs -> 7 (errno = 11 (Resource temporarily unavailable))
16:15:19.607: 4: FAIL: mntns_ghost01.c:121: Test died (errno = 11 (Resource temporarily unavailable))
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previousely I din't mention this case because we had bad error handling
in ghost cleanup path.
Without these patch but with proper error handling for unlink we have an
error in mntns_ghost01 test:
Error (criu/files-reg.c:2269): Failed to unlink the remap file:
Read-only file system
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/151c859e1
Changes: check lookup_mnt_id return for NULL
Fixes: fd0a3cd9ef ("mount: remount ro mounts writable before
ghost-file restore")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previousely remounted_rw was not shared between all processes on
restore, thus cleanup didn't got this info from rfi_remap and these
mounts were wrongly left writable after restore.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/3a1a592e7
Fixes: fd0a3cd9ef ("mount: remount ro mounts writable before
ghost-file restore")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If unlinkat fails it means that fs is in "corrupted" state - spoiled
with non-unlinked auxiliary directories.
While on it add fixme note as this function can be racy and BUG_ON if
path contains double slashes.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/b7b4e69fd
Changes: simplify while loop condition, remove confusing FIXME, remove
excess !count check in favour of while loop condition check
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
1) On error paths need to close fd and unlock mutex.
2) Make rfi_remap return special return code to identify EEXIST from
linkat_hard, all other errors should be reported up.
3) Report unlinkat error as criu should not corrupt fs.
Cherry-picked from Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/fe1d0be14
Changes: use close_safe(), fix order in "Fake %s -> %s link" error
message.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Always wait() for forked child processes. It avoid zombie processes in
containers that don't have an init process reaping orphans.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
CentOS 8 goes EOL at the end of 2021. This switches our CentOS 8 based
tests to CentOS Stream 8 which should be supported until 2024.
Signed-off-by: Adrian Reber <areber@redhat.com>
Criu ignores SIGPIPE in most cases except swrk mode. And in the
following situtation criu get killed by SIGPIPE and have no chance
to do cleanup: Connection to page server is lost when we do disk-less
migration, criu send PS_IOV_FLUSH via a broken connction in
disconnect_from_page_server.
This patch let criu ignore SIGPIPE in all paths .
Signed-off-by: Liu Hua <weldonliu@tencent.com>
Now when we fixed clang-format complains in zdtm, let's switch to lates
clang-format available. This is effectively a revert of commit 07a2f0265
("ci: use Fedora 34 for lint CI runs").
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The new freezer_state is a complete equivalent of old freezer_thawed
except for the initial value. If old freezer_thawed was not initialized
it was 0 and in freezer_restore_state were threated as if we need to
freeze cgroup "back", thus before this patch if criu dump failed before
freezing dumpee, criu always freeze dumpee in cr_dump_finish which is
wrong. Switching to freezer_state initialized with FREEZER_ERROR fixes
the problem.
v2: improve description, rename to origin_freezer_state
Signed-off-by: Liu Hua <weldonliu@tencent.com>
Clang-format v13 on my Fedora 35 complains about these hunks, more over
reading the formating we had before is a pain:
} else /* comment */
if (smth) {
fail("")
return -1;
}
Let's make explicit {} braces for else, this way it looks much better.
Fixes: 93dd984ca ("Run 'make indent' on all C files")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Various I/O objects are unclosed when the object falls out of scope.
This can lead to non-deterministic behavior.
Also fixed a few missing list(). It doesn't play way with python3.
e.g., `random.shuffle(filter(...))` doesn't work.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
We see that tests mntns_ghost01 and unlink_fstat03 can run
simultaneousely and thus the former sees leftover link_remap.* files in
the test directory created by the latter, and the latter is still
running so it's ok to have link_remap.* at this point.
Let's implicitly make all --link-remap tests exclusive (not running in
parallel).
Fixes: #1633
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We see error in centos8 ci on restore of socket-raw test:
inet: \tRestore: family AF_INET type SOCK_RAW proto 66
port 66 state TCP_CLOSE src_addr 0.0.0.0
Error (criu/sk-inet.c:834): inet: Can't create inet socket:
Protocol not supported
Centos 8 kernel replaces IPPROTO_MPTCP(262) with "in-kernel" value
IPPROTO_MPTCP_KERN(66) on inet_create(), but later shows this inkernel
value to criu when listing sockets info. Same code in inet_create()
returns EPROTONOSUPPORT on the attempr to create socket with
IPPROTO_MPTCP_KERN. So this ci error is completely rh8 kernel related.
Kernel should not show "in-kernel" value to userspace. But anyway this
is already changed in Centos 9 kernel, so we can just skip socket-raw
test on Centos 8.
v2: use cirrus.yml
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
There is no option in clang not to merge as much binary operands as it
fits in column limit, but here we need each bit on new line to make it
readable, so let's disable clang-format for x86_ins_capability_masks.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
A zombie process with 0 sid has a session leader in
outer pidns and has ignored SIGHUP. Criu has no idea
to restore this type of process, so fail the dumpping.
Signed-off-by: Liu Hua <weldonliu@tencent.com>
Automatic AlignTrailingComments fails to make those comments look right,
so let's do it manually, so that they both satisfy AlignTrailingComments
and also are human-readable.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Just set all possible values 0-3 and chack if it persists.
Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
When one sets socket buffer sizes with setsockopt(SO_{SND,RCV}BUF*),
kernel sets coresponding SOCK_SNDBUF_LOCK or SOCK_RCVBUF_LOCK flags on
struct sock. It means that such a socket with explicitly changed buffer
size can not be auto-adjusted by kernel (e.g. if there is free memory
kernel can auto-increase default socket buffers to improve perfomance).
(see tcp_fixup_rcvbuf() and tcp_sndbuf_expand())
CRIU is always changing buf sizes on restore, that means that all
sockets receive lock flags on struct sock and become non-auto-adjusted
after migration. In some cases it can decrease perfomance of network
connections quite a lot.
So let's c/r socket buf locks (SO_BUF_LOCKS), so that sockets for which
auto-adjustment is available does not lose it.
Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is a new kernel feature to let criu restore sockets with kernel
auto-adjusted buffer sizes.
Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We want to also c/r socket buf locks (SO_BUF_LOCKS) which are also
implicitly set by setsockopt(SO_{SND,RCV}BUF*), so we need to order
these two properly. That's why we need to wait for sk_setbufs to finish.
And there is no much point in seting buffer sizes asyncronously anyway.
Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
When exceptions are raised during testing, the image streamer process
should be terminated as opposed to being left hanging.
This could lead to the whole test suite to be left hanging as it waits
for all child processes to exit.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Fedora 35 comes with clang 13 which provides different results for
clang-format than clang 12 in Fedora 34.
Signed-off-by: Adrian Reber <areber@redhat.com>
Newer kernels (5.11) require echo 1 > /proc/sys/vm/unprivileged_userfaultfd
Without the 'echo 1' the kernel prints a message like this:
uffd: Set unprivileged_userfaultfd sysctl knob to 1 if kernel faults must be handled without obtaining CAP_SYS_PTRACE capability
Signed-off-by: Adrian Reber <areber@redhat.com>
Previously, `open_image(CR_FD_RULE, O_RSTR, pid)` was called twice.
Opening an image file twice is not allowed when streaming the image.
This commit optimizes the code to only open the image file once.
Also improved the error path in restore_ip_dump().
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
We see that on criu-ns dump/restore/dump of the process which initially
was not a session leader (with --shell-job option) we see sid == 0 for
it and fail with something like:
Error (criu/cr-dump.c:1333): A session leader of 41585(41585) is outside of its pid namespace
Note: We should not dump processes with sid 0 (even with --shell-job) as
on restore we can can put such processes from multiple sessions into
one, which is wrong.
Fixes: #232
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This simplifies the code by removing excess recursion and reusing
standard function to walk over file-tree instead of opencoding it.
This addresses problem mentioned in my review comment:
https://github.com/checkpoint-restore/criu/pull/1495#discussion_r677554523
Fixes: 0db135ac4 ("util: add rm -rf function")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
v2: split error checking from index variable initialization
v3: use PRIx64 for printing dev_t
Signed-off-by: fu.lin <fulin10@huawei.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We use here "%#x" printf specifier in pie code, but sbuf_printf core pie
printing function knows nothing about '#' specifier. More over simple
"%x" in pie does same as "%#x" in stdio printf, see print_hex* functions
add "0x" before hex numbers.
We've got this error on vzt-cpt runs in Virtuozzo:
(04.750271) pie: 158: Adjust id
Error: Unknown printf format %#
So to fix it we can just remove '#'.
Fixes: ecd432fe2 ("timerfd: Implement c/r procedure")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
ShellCheck reports the following problems:
SC2086: Double quote to prevent globbing and word splitting.
SC2035: Use ./*glob* or -- *glob* so names with dashes won't become options.
SC1091: Not following: ../env.sh was not specified as input (see shellcheck -x).
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
The shebang line in this file was removed in a previous commit and the
file should be non-executable.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
Previous commit added support for python3 in criu-coredump. For convenience,
add two files (coredump-python2 and coredump-python3) that start
criu-coredump with respective python version. Edit env.sh accordingly.
Signed-off-by: Andrey Vyazovtsev <viazovtsev.av@phystech.edu>
Resolve the following python3 portability issues:
1) Python 3 needs explicit relative import path.
2) Coredumps are binary data, not unicode strings. Use byte strings
(b"" instead of "") and open files in binary format.
3) Some functions (for example: filter) return a list in python 2,
but an iterator in python 3. Port code to a common subset of python 2
and python 3 using itertool.
4) Division operator / changed meaning in Python 3. Use explicit
integer division (//) where appropriate.
Signed-off-by: Andrey Vyazovtsev <viazovtsev.av@phystech.edu>
The expected behavior of --tcp-close option when dumpping is to close
all established tcp connections including connection that is once
established but now closed. This adds an explicit description about
that behavior.
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Since commit e42f5e0 ("tcp: allow to specify --tcp-close on dump"),
--tcp-close option can be used when checkpointing. This option skips
checkpointing established socket's state (including once established
but now closed socket). However, when restoring, we still try to
restore closed socket's state. As a result, a non-existent protobuf
image is opened.
This commit skips TCP_CLOSE socket when restoring established TCP
connection and removes the redundant check for TCP_LISTEN socket as
TCP_LISTEN socket cannot reach this function.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Suggested-by: Radostin Stoyanov <radostin@redhat.com>
Signed-off-by: Bui Quang Minh <minhquangbui99@gmail.com>
Restore operation fails when we perform CR operation of multiple
independent proceses that have device files because criu caches
the ids for the device files with same mnt_ids, inode pair. This
change ensures that even in case of a cached id found for a device, a
unique subid is generated and returned which is used for dumping.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
This is just a placeholder dummy plugin and will be replaced by a proper
plugin that implements support for AMD GPU devices. This just
facilitates the initial pull request and CI build test trigger for early
code review of CRIU specific changes. Future PRs will bring in more
support for amdgpu_plugin to enable CRIU with AMD ROCm.
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Currently CRIU cannot handle Checkpoint Restore operations when a device
file is involved in a process, however, CRIU allows flexible extensions
via special plugins but still, for certain complex devices such as a GPU,
the existing hooks are not sufficient. This introduces few new hooks
that will be used to support Checkpoint Restore operation with AMD GPU
devices and potentially to other similar devices too.
- HANDLE_DEVICE_VMA
- UPDATE_VMA_MAP
- RESUME_DEVICES_LATE
*HANDLE_DEVICE_VMA:
Hook to detect a suitable plugin to handle device file VMA with
PF | IO mappings.
*UPDATE_VMA_MAP:
Hook to handle VMAs during a device file restore.
When restoring VMAs for the device files, criu runs sys_mmap in
the pie restore context but the offsets and file path within a
device file may change during restore operation so it needs to be
adjusted properly.
*RESUME_DEVICES_LATE:
Hook to do some special handling in late restore phase.
During criu restore phase when a device is getting restored with
the help of a plugin, some device specific operations might need
to be delayed until criu finalizes the VMA placements in address
space of the target process. But by the time criu finalizes this,
its too late since pie phase is over and control is back to criu
master process. This hook allows an external trigger to each
resuming task to check whether it has a device specific operation
pending such as issuing an ioctl call? Since this is called from
criu master process context, supply the pid of the target process
and give a chance to each plugin registered to run device
specific operation if the target pid is valid.
A future patch will add consumers for these plugin hooks to support AMD
GPUs.
Signed-off-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Support for external net namespaces has been introduced with
commit c2b21fbf (criu: add support for external net namespaces).
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
* Switch criu-ns from unversioned 'python' to 'python3'
for easier distribution packaging
* Add '--join-ns' interface to libcriu to allow joining
namespaces via libcriu like CLI and RPC already allow
Signed-off-by: Adrian Reber <areber@redhat.com>
run_test was trying to read criu logs on build failure
instead of runtime error.
This patch also removes the unnecessary subfolder with name "i"
and resolves some of issues reported by shellcheck.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
This test case aims to verify that CRIU correctly
restores a process in IPC, UTS and Time namespaces
with criu_join_ns_add() libcriu API.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
In runc we use the join-ns RPC API to enable checkpoint/restore of
containers with shared namespaces. Shared namespaces are often used
when containers run inside Kubernetes Pod.
In crun we use libcriu to interface with CRIU, however it currently
doesn't provide an API for join-ns. This patch adds the necessary
libcriu API to enable checkpoint/restore of containers with shared
namespaces with crun.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
Python 2 has been deprecated since January 1, 2020 and linux distributions
already support Python 3. Thus, to simplify maintenance and packaging
we could support criu-ns as Python 3 only.
v2: Add a message for criu-ns installation
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
PEP 394 recommends changing python shebangs to python3 when Python 3.x
is supported. This is similar to `crit-python3`.
https://www.python.org/dev/peps/pep-0394/
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
Amongst a huge number of fixes all over the place and the move away from
Travis this release introduces:
* better support for restoring containers into existing pods
* pidfd based pid reuse detection for RPC clients
* allow restoring of precreated veth devices
* license change for all files in the images/ directory to MIT
* criu-ns helper script
* use clang-format for automatic code indentation
* support checkpoint/restore of stacked apparmor profiles
* [GSoC] Add nftables based network locking/unlocking (Zeyad Yasser)
Signed-off-by: Adrian Reber <areber@redhat.com>
In the function dump_one_fs(), there's a comment that says "mnt_bind is
a cycled list, so list_for_each can't be used here." That means that the
list head of the list is also a node of the list.
The subsequent list_for_each_entry() marks all the mount info nodes as
dumped, except it skips the list head, which is also a mount info.
This is the bug we fix.
This bug made CRIU dump a file system twice.
See https://github.com/checkpoint-restore/criu-image-streamer/issues/8
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
The build directory is generated when running make install.
build/ was initially added to gitignore with commit 967797a (Add build
directory to gitignore) and it was accidentally removed.
Signed-off-by: Radostin Stoyanov <radostin@redhat.com>
If we save root and cwd after we've already switched to mntns we save
different root and cwd from what we had before prep_unix_sk_cwd, we just
save default root/cwd for new mntns... Let's fix it by proper order.
Also while on it lets fix ns_fd leak on switch_ns_by_fd error path.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
There was a race window in kerndat_has_nftables_concat(void) when
two or more instances of CRIU are running in parallel.
One instance would create the table normally, and another would
fail when trying to create a table with the same name and wrongly
set kdat.has_nftables_concat = false, and will save it to kerndat
cache.
A separate netns is created to avoid table collisions.
v2: use call_in_child_process helper instead of fork
Co-developed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
In test/jenkins/{crit.sh,criu-dump}, ZDTM is run with --norst,
Causing tests to only go through dump wihtout restoring.
The network locking tests are highly dependant on dump/restore hooks
causing them to hang when run with --norst.
We just add a reqrst flag to all network lock tests.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
During network locking CRIU creates an nftables table to
add needed rules. If more than one instance of CRIU run
in parallel, those tables' names would conflict.
Solution is to append root task pid to the nftables table
name as a postfix (e.g. inet CRIU-3231).
We also need to use `create table` instead of `add table`
because using `create` returns an error in case table name
already exists so we could detect conflicts if they happen.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
When the network is locked using a specific method like iptables
or nftables there is no need to require passing the same method
during restore.
We save the lock method during dump in the inventory image and
use that in restore.
This always overwrites the restore --network-lock option.
v2: store opts.network_lock_method directly to avoid dependency
on rpc.proto's 'enum criu_network_lock_method'.
v3: fall back to iptables if image is generated with an older
version of CRIU.
v4: remove --network-lock from netns_lock_* from restore
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
v2: remove unnecessary elif and else after return in
wait_server_addr()
v3: use IOError instead of FileNotFoundError for python2
compatibility
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This is just a symlink to the original static/net_lock_socket_iptables
test with the right options passed to use nftables instead.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This adds nftables based connection locking as an alernative
for iptables. This avoid the external dependency of
iptables-restore.
It works by creating a 'connection set', which is a set of
connection identifying tuples. Rules are added to drop packets that
match the connection tuples in the set. Locking is now reduced to
just adding the connection identifying tuple to the set.
Unlocking is just as simple as deleteing the CRIU table.
v2: split ip string conversion into two if conditions
v3: add better message when CRIU is build without libnftables support
v4: fix indentation in nftables_lock_connection_raw()
v5: move 'ret = -1' below err: lable to avoid redundancy
v6: add better error message on lock failure
v7: run make indent
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
When criu dumps a process with --tcp-established opt it locks
the open tcp connections so that no packets from peer enters
the stack, otherwise RST will be sent by a kernel causing the
connection to fail.
Post-start hook creates a connection with the test server and
creates a background thread that stays alive for the duration
of the test. This background thread sends data to the test
server at three stages:
- Pre-dump: Should send normally
- Pre-restore:
If connection is locked properly, packets will be dropped
and TCP will just retry, which will eventually be sent when
the process is restored and the network is unlocked.
- Post-restore: Should send normally
Data sent at the three stages is then checked at the server's side.
v2:
- remove unused imports and constants
- delete sync file in wait_sync_file() instead of --clean
v3:
- add comments
Co-developed-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This is just a symlink to the original static/netns_lock test with
the right options passed to use nftables instead.
v2:
- make static/netns_lock test iptables explicitly
- prevent netns_lock tests from running in parallel because
netns & sync files creation were conflicting in both tests.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This adds nftables based internal network locking as an
alernative for iptables. This avoid the external dependency
of iptables-restore.
v2: fix indentation & rename 'free' lable to 'out'
v3: add better message when CRIU is build without libnftables support
v4:
- move 'ret = -1' below err: lable to avoid redundancy
- fix nft ctx memory leak in case of success in
nftables_network_unlock()
v5: add better error message on lock failure
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
Related to the new --network-lock option, other methods for network
locking/unlocking will be added as an alternative to iptables like
nftables.
This option is used in the core network locking/unlocking hooks to
decide which method should be used, making it easier to add new
methods later smoothly.
i.e.
- network_lock_internal
- network_unlock_internal
- lock_connection (renamed from nf_lock_connection)
- unlock_connection (renamed from nf_unlock_connection)
- unlock_connection_info (renamed from unlock_connection_info)
nf_* functions are renamed to iptables_* to avoid confusion with
other netfilter methods in the future like nftables.
v2: run make indent
v3: make error messages more descriptive
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
Nftables based network locking/unlocking will be added later.
Nftables sets will be used to load the connection tuples that
will be locked, to be able to store those tuples we need to
check "Set Concatenations" support.
https://wiki.nftables.org/wiki-nftables/index.php/Concatenations
v2: fix 'has_nftables_concat=true' when adding CRIU table fails
v3: add better message when CRIU is build without libnftables support
v4: run make indent
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
This adds the option to choose the networking locking method.
CRIU currently uses iptables-restore cli for network locking/unlocking
but nftables support will be added later.
There have been reports from users that iptables-restore fails in some
way and an nftables based approach using libnftables could avoid this
external dependency.
v2: remove dependency details in man page for --network-lock.
v3: remove --network-lock from restore section in docs because it is
automatically detected from the inventory image now.
v4: add message that --network-lock will be ignored during restore
and value from dump will be used.
v5: run make indent
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
We have some code written with the assumption that argv is never
destroyed, but when we handle configs, we construct an argv-like array
for each config, parse it and release it.
I am still not sure that we need to release memory of per-config argv
arrays... The current scheme is going to be a source of used-after-free
bugs. When we will add the non-privileged mode, all these bugs will be
serious security issues.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Without any LSM detected CRIU would print a warning for every run:
Warn (criu/lsm.c:328): don't know how to suspend LSM 0
Which clutters up the CI logs.
Change the message to a debug message.
Signed-off-by: Adrian Reber <areber@redhat.com>
On systems where there is no build_id we get a warning for each run
Warn (criu/files-reg.c:1458): Couldn't find the build-id note for file with fd 15
Change the log level to debug for this message as the file just does not have
a build_id and printing a warning clutters the CI logs.
Signed-off-by: Adrian Reber <areber@redhat.com>
On Virtuozzo7 jenkins we see a fail of criu-dev zdtm:
===================== Run zdtm/static/pthread_timers in ns =====================
Start test
./pthread_timers --pidfile=pthread_timers.pid --outfile=pthread_timers.out
Run criu dump
=[log]=> dump/zdtm/static/pthread_timers/112/1/dump.log
------------------------ grep Error ------------------------
(00.004817) netlink: Collect netlink sock 0x1cad6e21
(00.004821) netlink: Collect netlink sock 0x1cad6e22
(00.004831) Collecting pidns 9/112
(00.004886) No parent images directory provided
(00.004903) Warn (criu/lsm.c:328): don't know how to suspend LSM 0
------------------------ ERROR OVER ------------------------
Run criu restore
4: Old maps lost: set([])
4: New maps appeared: set([u'7fe4c54ca000-7fe4c54cb000 ---p', u'7fe4c0000000-7fe4c0021000 rw-p', u'7fe4c0021000-7fe4c4000000 ---p', u'7fe4c54cb000-7fe4c5ccb000 rw-p'])
############# Test zdtm/static/pthread_timers FAIL at maps compare #############
https://ci.openvz.org/job/CRIU/job/CRIU-virtuozzo/job/criu-dev/8032/consoleFull
First thing to mention is that this is not related to criu. I can manage
to reproduce it with "--nocr", problem is that some mapping appears a
bit later when we do pre-cr get_visible_state().
By debugging SIGEV_THREAD thread with gdb I can see that addresses from
this unexpectedly appearing mapping are used by glibc here as "struct
pthread *pd":
clone()
start_thread()
timer_helper_thread()
__pthread_create_2_1()
So the mapping looks allocated by allocate_stack(), and it is only
gets done after first timer trigger (we have glibc-2.17 on vz7):
https://github.com/bminor/glibc/blob/release/2.17/master/nptl/sysdeps/unix/sysv/linux/timer_routines.c#L92
So let's wait at least 1 timer trigger so that memory outfit of the test
become permanent and our check_visible_state zdtm check would not be
false negative.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Jenkins test runs are failing with:
./test/jenkins/run_ct ./test/jenkins/crit.sh
./test/jenkins/crit.sh: 3: source: not found
Switch to bash which has 'source'.
Signed-off-by: Adrian Reber <areber@redhat.com>
The following error occurs when creating a checkpoint of
a container immediately after the container has been restored
from another checkpoint.
Error response from daemon: Cannot checkpoint container cr: content
sha256:12c69b7a9d25695dd5f9d37d4e858e2f7c3f9da738ccf86f8d3042f6973af1df:
already exists
In this patch we add a healthcheck to the test container and update the
test to perform a checkpoint only when the container is in a 'healthy'
state. In addition, this patch adds a scenario to test the
checkpoint/restore of multiple containers.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Otherwise, criu pre-dump can fail with errors like this:
lib/infect.c:650: Unable to connect a transport socket: Permission denied'
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@gmail.com>
AppArmor namespaces are officially colon-separated. The double-slash
syntax is just convenience:
"The trailing : separates the namespace name from the profile name and
the optional / and // separators are provided as a convenience for those
familiar with ssh and protocol urls." (see [1])
[1]: https://gitlab.com/apparmor/apparmor/-/wikis/AppArmorNamespaces
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
The original patches didn't pass down the "suspend" boolean into
write_aa_policy() and so suspend never really happened. Pass it down.
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
v2: use a profile that doesn't have "unix" to test the suspend feature too
v3: use "/" in the profile names to make sure this works
Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Support for apparmor namespaces and stacking is coming to Ubuntu kernels in
16.10, and should hopefully be upstreamed Soon (TM) :).
The basic idea is similar to how cgroups are done: we can restore the
apparmor namespace and profile blobs independently of the tasks, and then
at the end we can just set the task's label appropriately. This means the
code that moves tasks under a label stays the same, and the only new code
is the stuff that dumps and restores the policy blobs that are in the
namespace that were loaded by the container.
Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
Instead of collecting profiles right at thread dump time, let's collect
them all at a single point. This way, when we add support for suspending
LSMs, we know what profiles if any we need to suspend.
Signed-off-by: Tycho Andersen <tycho.andersen@canonical.com>
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This is another attempt to introduce a tool to format CRIU's source
code. This time it is based on clang-format.
The .clang-format file is taken from the linux kernel git tree (5.13).
I removed all comments from lines which state that it requires at least
clang-format 4 or 5. For this resulting file at least clang-format 11
is required. See scripts/fetch-clang-format.sh for all the changes
done to the Linux kernel .clang-format file.
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Fedora Rawhide updated to a glibc using clone3(). clone3() is, however,
not yet part of the seccomp filter. Unfortunately 'docker build' does
not allow dropping seccomp but luckily 'podman build' does.
This switches the Fedora Rawhide test to use Podman. Podman is part of
GitHub Actions and no additional packages need to be installed.
Signed-off-by: Adrian Reber <areber@redhat.com>
If retcode of dump_posix_timers is not zero it is treated as an error in
compel_rpc_sync. And currently we can return positive overrun of last
timer (if we are lucky and it is not zero) as retcode of function
dump_posix_timers, let's fix it. Also I don't see any point in putting
negative value into .overrun on error path, fix it too.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Resolving real pid to vpid for notify thread ids requires NSpid feature
supported by kernel, though in simple non-pid-ns case we can deal
without it, so add a requirement and split out the host test without the
requirement.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
1) If all dumped processes are in host pidns we can skip pid conversion
logic and just use real pid.
2) If we have pidns to dump we should also have kernel NSpid feature,
else we should fail to dump notify thread id, as it's not possible to
properly convert rpid to vpid.
While on it let's put the code to encode_notify_thread_id helper to
improve code readability.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On Centos7 we don't have NSpid field in /proc/[pid]/status so for
compatibility let's skip it.
(cherry-pick one hunk from Virtuozzo commit
https://src.openvz.org/projects/OVZ/repos/criu/commits/c6d0ee567c)
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If there is nested pid_ns, we need to be able to get pid in
the whole pid hierarhy. This may be taken from "/proc/[pid]/status"
file only. Check, that kernel has support for it.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
NSpid is not (yet) supported on Centos7 thus we need this check for
compatibility.
(cherry-picked from Virtuozzo criu commit
https://src.openvz.org/projects/OVZ/repos/criu/commits/94f4653f20)
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
When sigev_notify_thread_id is not set, get_pid will return a NULL
pointer and do_timer_create will return -EINVAL in kernel. So criu
will failed to create posix timer:
(09.806760) pie: 41301: Error (criu/pie/restorer.c:1998): Can't restore posix timers -22
(09.806824) pie: 41301: Error (criu/pie/restorer.c:2133): Restorer fail 41301
(09.891880) Error (criu/cr-restore.c:2596): Restoring FAILED.
Signed-off-by: Liu Chao <liuchao173@huawei.com>
Prioritize /lib/* because iptables fails to search /usr/lib64/*
first on archlinux.
This change of 'deps' order prioritizes the default library location.
This affects:
- zdtm/static/netns-nf
- zdtm/static/netns-nft-ipt
- zdtm/static/socket-tcp-closed-last-ack
- zdtm/static/socket-tcp-reseted
- zdtm/static/socket-tcp-syn-sent
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
Fixes: #1560
The latest protobuf-c compiler breaks CRIU because they removed
leading underscores from structs in 1.4.0.
This replaces those definitions with the standard generated structs.
v2: remove struct _VmaEntry, struct _CredsEntry and struct _CoreEntry
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
Make sure to remove all files created from previous local build
before compiling in the container.
Reported-by: Rajneesh Bhardwaj <rajneesh.bhardwaj@amd.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This is useful to investigate problems on pre-dump iterations. After
this patch test output with "--pre=2 --sbs" would have new usefull stop
points.
While on it let's remove confusion in sbs stop point naming. "Pause at
pre-dump" actually has nothing to do with pre-dump, let's better use
"before " instead of "at pre-", similar let's use "after " instead of
"at post-".
Result would look like:
========================== Run zdtm/static/env00 in h ==========================
Start test
./env00 --pidfile=env00.pid --outfile=env00.out --envname=ENV_00_TEST
Pause before pre-dump 0. Press Enter to continue.
Run criu pre-dump
Pause before pre-dump 1. Press Enter to continue.
Run criu pre-dump
Pause before dump. Press Enter to continue.
Run criu dump
Pause before restore. Press Enter to continue.
Run criu restore
Pause after restore. Press Enter to continue.
v2: improve sbs step naming; rename "iter" to more meaningfull
"pre-dump"/"snap".
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cgroup yard is setup in crtools_prepare_shared. But it is not cleaned up
properly in some code path, which leads cgroup mountpoint leaking.
Signed-off-by: Liu Hua <weldonliu@tencent.com>
The cross compile container definitions for each architecture were
almost the same files except for the architecture.
This moves the architecture to variables so that all cross compile
setups can use the same container definition.
Signed-off-by: Adrian Reber <areber@redhat.com>
Else we get error:
[root@fedora criu]# crit/crit x test/dump/zdtm/static/memfd00/56/1/ mems
...
Traceback (most recent call last):
File "/home/snorch/devel/ms/criu/crit/crit", line 6, in <module>
cli.main()
File "/home/snorch/devel/ms/criu/crit/pycriu/cli.py", line 430, in main
opts["func"](opts)
File "/home/snorch/devel/ms/criu/crit/pycriu/cli.py", line 361, in explore
explorers[opts['what']](opts)
File "/home/snorch/devel/ms/criu/crit/pycriu/cli.py", line 283, in explore_mems
fn = ' ' + get_file_str(opts, {
File "/home/snorch/devel/ms/criu/crit/pycriu/cli.py", line 214, in get_file_str
f = ft['get'](opts, ft, fd['id'])
File "/home/snorch/devel/ms/criu/crit/pycriu/cli.py", line 165, in ftype_reg
rf = ftype_find_in_image(opts, ft, fid, 'reg-files.img')
File "/home/snorch/devel/ms/criu/crit/pycriu/cli.py", line 154, in ftype_find_in_image
return f[ft['field']]
KeyError: 'reg'
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Moved pidfd store hashtable initialization to cr-service.c since
pidfd_store is only relevant in RPC mode.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
There is no need to expose the internals of pidfd_store like
hash table entries and how to use them for pid reuse detection.
v2: fixup some spacing issues
v3: fix hash memory leak after xmalloc in init_pidfd_store_hash()
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
The --post-start hook creates a netns which the test should enter
at the beginning of the test.
The test randomly failed in CI tests, it is most likely caused by
a race condition.
I suspect this flow is root cause:
1. --post-start hook starts just after the test (in parallel)
2. --post-start hook calls ip netns add to create the test netns
3. ip creates the netns file
4. netns_lock test opens that file and uses it in setns
5. ip mounts the netns to the file
Of course test fails at step 4 because the netns is not yet mounted
to the file.
I made the test wait for SYNCFILE to be created by the --post-start
hook before it tries to open the netns file and call setns.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
The mips64el-cross test target started to show following error:
error: listing the stack pointer register '$29' in a clobber list is deprecated [-Werror=deprecated]
This fixes it in three different places by removing $29' from the
clobber list. This is only compile tested as we have no mips hardware
for testing.
Signed-off-by: Adrian Reber <areber@redhat.com>
If inherit-fd is read from a config file its buffer will be freed
after the config file is parsed but before task restore, which is
when we need to use the mapping. Therefore, when adding an
inherit-fd mapping to the opts list, copy the key string to a new
buffer.
Signed-off-by: Younes Manton <ymanton@ca.ibm.com>
It will broken when the cli `crit show ipcns-shm-9.img` is executed, msg:
{
"magic": "IPCNS_SHM",
"entries": [
{
"desc": {
"key": 0,
"uid": 0,
"gid": 0,
"cuid": 0,
"cgid": 0,
"mode": 438,
"id": 0
},
"size": 1048576,
"in_pagemaps": true,
"extra": Traceback (most recent call last):
File "/usr/bin/crit", line 6, in <module>
cli.main()
File "/usr/lib/python3/dist-packages/pycriu/cli.py", line 412, in main
opts["func"](opts)
File "/usr/lib/python3/dist-packages/pycriu/cli.py", line 45, in decode
json.dump(img, f, indent=indent)
File "/usr/lib/python3.9/json/__init__.py", line 179, in dump
for chunk in iterable:
File "/usr/lib/python3.9/json/encoder.py", line 431, in _iterencode
yield from _iterencode_dict(o, _current_indent_level)
File "/usr/lib/python3.9/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/usr/lib/python3.9/json/encoder.py", line 325, in _iterencode_list
yield from chunks
File "/usr/lib/python3.9/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/usr/lib/python3.9/json/encoder.py", line 438, in _iterencode
o = _default(o)
File "/usr/lib/python3.9/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable
This is caused by `img['magic'][0]['extra']` which is bytes. I find
other load condtions, fix them at the same time.
Signed-off-by: fu.lin <fulin10@huawei.com>
This change is motivated by checkpointing and restoring container in
Pods.
When restoring a container into a new Pod the SELinux label of the
existing Pod needs to be used and not the SELinux label saved during
checkpointing.
The option --lsm-profile already enables changing of process SELinux
labels on restore. If there are, however, tmpfs checkpointed they
will be mounted during restore with the same context as during
checkpointing. This can look like the following example:
context="system_u:object_r:container_file_t:s0:c82,c137"
On restore we want to change this context to match the mount label of
the Pod this container is restored into. Changing of the mount label
is now possible with the new option --mount-context:
criu restore --mount-context "system_u:object_r:container_file_t:s0:c204,c495"
This will lead to mount options being changed to
context="system_u:object_r:container_file_t:s0:c204,c495"
Now the restored container can access all the files in the container
again.
This has been tested in combination with runc and CRI-O.
Signed-off-by: Adrian Reber <areber@redhat.com>
When criu dumps a process in a network namespace it locks
the network so that no packets from peer enters the stack,
otherwise RST will be sent by a kernel causing the connection
to fail.
In netns_lock.c we try to enter the netns created by post-start
hook so that criu locks the network namespace between dump and
restore.
A TCP server is started in post-start hook inside the test netns
and runs in the background detached from its parent so that
it stays alive for the duration of the test.
Other hooks (pre-dump, pre-restore, post-restore) try to
connect to the server.
Pre-dump and post-restore hooks should be able to connect
successfully.
Pre-restore hook client with SOCCR_MARK should also connect
successfully.
Pre-restore hook client without SOCCR_MARK should not be able
to connect but also should not get connection refused as all
packets are dropped in the namespace so the kernel shouldn't
send an RST packet as a result. Instead we check that the
connect operation causes a timeout.
This test would be useful when testing that the network is
locked using different ways (using iptables currently and
other methods later).
v2:
- check that packets with SOCCR_MARK are allowed to
pass when the netns is locked.
v3:
- fix pre-restore hook skipping non SOCCR_MARK
connection test due to early exit in SOCCR_MARK
variant.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
criu exec is deprecated for some time now and criu just exits with an
error if running 'criu exec'. This removes the test for that non-working
subcommand.
Signed-off-by: Adrian Reber <areber@redhat.com>
This adds a test run to ensure known (but fixed) configuration file
parser errors are not crashing CRIU anymore.
Based on missing test code coverage this script also tests code paths of
the option handling which have not been tested until now.
Signed-off-by: Adrian Reber <areber@redhat.com>
Trying to see how robust the configuration parser I was able to crash
CRIU pretty quickly. This fixes a few crashes in the existing
configuration file parser.
Signed-off-by: Adrian Reber <areber@redhat.com>
The callers of bread() and bwrite() assume the operation reads/writes
the complete length of the passed buffer.
We must loop when invoking the read()/write() APIs.
Fixes#1504
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Now that we are running CI on an actual CentOS 7 kernel different
tests are no longer working as they require newer kernels.
This commit disables a few tests only on CentOS 7.
Signed-off-by: Adrian Reber <areber@redhat.com>
This commit removes a couple of workaround for old kernels and
distributions which we no longer use in CI.
Signed-off-by: Adrian Reber <areber@redhat.com>
On Cirrus CI we can run tests on the orignal CentOS 7 kernel.
The kernel is rather old, but on GitHub Actions we a 5.8 kernel
and a containerized CentOS 7 user space not much is working
correctly anymore. With this commit CentOS 7 based tests are
no longer running on GitHub Actions but on Cirrus CI.
Signed-off-by: Adrian Reber <areber@redhat.com>
With this change tainted kernels can be ignored with setting
ZDTM_IGNORE_TAINT=1. This is just to simplify the CI script to not
require to change every call of zdtm. Setting the variable once should
be enough.
Signed-off-by: Adrian Reber <areber@redhat.com>
These files use $PKG_CONFIG before they include the common files that
setup a default, so set early defaults in them too.
Signed-off-by: Mike Frysinger <vapier@chromium.org>
The build needs to respect $PKG_CONFIG env var like other standard
build systems and the the upstream pkg-config project itself. This
allows the package builder to point it to the right tool when doing
a cross-compile build. Otherwise the host pkg-config tool is used
which won't have access to the packages in the cross sysroot.
Signed-off-by: Mike Frysinger <vapier@chromium.org>
This patch improves the changes from 19be9ced9.
To use the newer version of containerd, we need to make sure that the
containerd service has been restarted after install. Instead of
hard-coding a version number, we can use github API to get the latest
release. In addition, the tar file contains all binary files in a
'./bin' sub-folder. Thus, it should be extracted in '/usr'.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The tun_ns test was introduced with [1] and [2], however, these commits
didn't add per-test dependencies required for the test.
Per-test dependencies are listed in the .desc file as 'deps': [<list>]
These dependencies are made available inside the test namespace and without
the ip dependency, the tests fails on Fedora 34 with
Error: ipv4: FIB table does not exist.
[1] 7e355e7
[2] 3ba0893
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Although CentOS 8 comes with 4.18 kernel it has time namespace patches
backported but not all the required once. This disables time namespaced
tests on everything older than 5.11.
Signed-off-by: Adrian Reber <areber@redhat.com>
The SET_CHAR_OPT(__dest, __src) macro is essentially:
free(opts.__dest);
opts.__dest = xstrdup(__src);
So if __dest == __src the string that get's copied is freed. This e.g.
is the case in criu/lsm.c
int lsm_check_opts(void)
{
char *aux;
if (!opts.lsm_supplied)
return 0;
aux = strchr(opts.lsm_profile, ':');
if (aux == NULL) {
pr_err("invalid argument %s for --lsm-profile\n", opts.lsm_profile);
return -1;
}
*aux = '\0';
aux++;
if (strcmp(opts.lsm_profile, "apparmor") == 0) {
if (kdat.lsm != LSMTYPE__APPARMOR) {
pr_err("apparmor LSM specified but apparmor not supported by kernel\n");
return -1;
}
SET_CHAR_OPTS(lsm_profile, aux);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} else if (strcmp(opts.lsm_profile, "selinux") == 0) {
if (kdat.lsm != LSMTYPE__SELINUX) {
pr_err("selinux LSM specified but selinux not supported by kernel\n");
return -1;
}
SET_CHAR_OPTS(lsm_profile, aux);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
} else if (strcmp(opts.lsm_profile, "none") == 0) {
xfree(opts.lsm_profile);
opts.lsm_profile = NULL;
} else {
pr_err("unknown lsm %s\n", opts.lsm_profile);
return -1;
}
return 0;
}
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This way users would be able to create more meaningfull pull-requests
and issues. And we would not need to ask them to provide basic
information each time.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Previousely kerndat_uffd could not differentiate -EPERM and -1 returned
from uffd_open(). That way "Failed to get uffd API" and "Incompatible
uffd API ..." errors were just ignored, which is probably not what we
want.
v2: rework with extra argument of uffd_open for errno, rename err
label in uffd_open for readability
Fixes: cfdeac4a4 ("kerndat: Handle non-root mode when checking uffd")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Now that the Ubuntu kernel is no longer broken with regards to
overlayfs, let's switch back to overlayfs instead of devicemapper and
vfs graphdrivers.
Signed-off-by: Adrian Reber <areber@redhat.com>
There are several problems with the loop.sh script. First, the code is
duplicated across tests in the so-called 'othres' category. Second, we
need to run it with the 'setsid' utility to make sure that it runs in
a new session. Third, we have to redirect the standard file descriptors
and use the '&' operator to make it run in the background. Finally,
obtaining the PID of the 'loop.sh' process resulted in race condition.
In this patch we replace the loop.sh script with a program that would
address all problems mentioned above. The requirements for this program
are as follows.
- It must be reusable across tests
- It must start a process that is detached from the current shell
- It must wait for the process to start and output its PID
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The function name '_exit' is misleading as this function doesn't
actually exit when the status of the previous command is zero.
In addition, the behaviour of this function is not really needed.
This patch removes the '_exit' function and applies the correct
behaviour to stop the test on failure.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
One should never rely on errno if libc syscall is successful. We can
either see an errno set from some previous failed syscall or even errno
set by a this successful libc syscall. So lets check ret first.
Fixes: 1ccdaf47 ("criu: add pidfd based pid reuse detection for RPC
clients")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This is just a symlink to the original transition/pid_reuse test with
the right options passed to trigger the pidfd store based pid reuse
detection code path.
Pidfd store based detection is supported only in RPC mode which
requires passing a unix socket fd to be used as pidfd store and
the kernel should support pidfd_open and pidfd_getfd syscalls
{'feature': 'pidfd_store'} for this test to work.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
When testing pid reuse using pidfd_store feature in RPC mode we need
to pass a unix socket fd used to CRIU in the RPC option
pidfd_store_sk to store the pidfds between predump/dump iterations.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
Closes: #717
This increases the reliability of pid reuse detection using pidfds,
currently through RPC migration tools like P.Haul.
A connectionless unix socket is passed to criu in RPC mode through
the RPC option pidfd_store_sk.
If this option is set, the socket is initialized in
init_pidfd_store_sk() to be used as a queue for task pidfds.
criu then sends tasks pidfds to this socket in send_pidfd_entry()
and receives them in the next pre-dump/dump iteration to build
the pidfds hashtable in init_pidfd_store_hash().
These pidfds will be used later in detect_pid_reuse().
How it should be used in migration tools like P.Haul:
- Open a connectionless unix socket
- Pass the socket fd in the RPC option pidfd_store_sk when
doing a pre-dump or dump
This will fail if the kernel does not support pidfd_open or
pidfd_getfd syscalls, so pidfd_store_sk should not be set if the
kernel does not support pidfd_open.
This could be checked with:
CLI: criu check --feature pidfd_store
RPC: CRIU_REQ_TYPE__FEATURE_CHECK and set pidfd_store to
true in the "features" field of the request
v2:
- add reasonable polling restart limit in check_pidfd_entry_state
to avoid getting stuck
- avoid leaking pidfd in send_pidfd_entry when entry is NULL,
otherwise pidfds are freed in free_pidfd_store
v3:
- check that the passed pidfd store is not empty after
the first iteration (i.e. --prev-images-dir option set).
v4:
- clear pidfd_hash heads
- check entry allocation error in init_pidfd_store_hash()
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
pidfd_store which will be used for reliable pidfd based pid reuse
detection for RPC clients requires two recent syscalls (pidfd_open
and pidfd_getfd).
We allow checking if pidfd_store is supported using:
1. CLI: criu check --feature pidfd_store
2. RPC: CRIU_REQ_TYPE__FEATURE_CHECK and set pidfd_store to
true in the "features" field of the request
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
pidfd_store_sk option will be used later to store tasks pidfds
between predumps to detect pid reuse reliably.
pidfd_store_sk should be a fd of a connectionless unix socket.
init_pidfd_store_sk() steals the socket from the RPC client using
pidfd_getfd, checks that it is a connectionless unix socket and
checks if it is not initialized before (i.e. unnamed socket).
If not initialized the socket is first bound to an abstract name
(combination of the real pid/fd to avoid overlap), then it is
connected to itself hence allowing us to store the pidfds in the
receive queue of the socket (this is similar to how fdstore_init()
works).
v2:
- avoid close(pidfd) overriding errno of SYS_pidfd_open in
init_pidfd_store_sk()
- close pidfd_store_sk because we might have leftover from
previous iterations
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
pidfd_getfd syscall will be needed later to send pidfds between
pre-dump/dump iterations for pid reuse detection.
v2:
- check size written/read of val_a/val_b is correct
- return with error when val_a != val_b
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
pidfd_open syscall will be needed later to send pidfds between
pre-dump/dump iterations for pid reuse detection.
v2:
- make kerndat_has_pidfd_open void since 0 is always returned
- fix missing tabs in syscall tables
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
When criu is run as user it fails and exits because of kerndat_uffd() returning -1.
This, in turn, happens after uffd = syscall(SYS_userfaultfd, flags); which only works
for root.
In the change it ignores the permission error and proceeds further just like it's done
for e.g. pagemap checking.
Signed-off-by: Nithin Jaikar J <jaikar006@gmail.com>
This commit extends the CRIT tests to cover the 'x' command, which is
used to explore an image directory.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This is the workaround for #1429.
The parasite code contains instructions that trigger SIGTRAP to stop at
certain points. In such cases, the kernel sends a force SIGTRAP that
can't be ignore and if it is blocked, the kernel resets its signal
handler to a default one and unblocks it. It means that if we want to
save the origin signal handle
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This testcase reproduces deadlock in "wait_fds_event" futex in open_fdinfos()
function (files subsystem).
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
This patch fixes deadlock that appears on ghost DGRAM unix sockets.
Problem is that wake_connected_sockets() function *should* be called
strictly after fle->stage >= FLE_OPEN.
Explanation:
Consider situation, we have ghost unix DGRAM socket (peer socket),
and also have several sockets that connected to this peer socket.
How restore of that picture works?
In files subsystem we have open_fdinfos(pstree_item*) function that calls open_fd()
function for *every* fd of task. open_fd() function calls appropriate
file descriptor "open" handler that may return "1" which means "try again later".
This retcode means, that some additional resources is needed to fully restore file
descriptor. For *ghost* UNIX sockets, for instance, we need to have peer socket
file descriptor *before* we can open and restore client sockets. Here is the main problem.
open_fdinfos() called from separate tasks simultaneously, so, when we get "1" retcode
we stay on futex (wait_fds_event() function) and waiting for someone another task
restore some resource and notify us that we can retry opening of file descriptor.
With *ghost* UNIX socket I've managed to caught next behaviour.
1. From one task (that holds client socket) open_fdinfos() called open_fd() that called
open_unixsk_standalone(). In open_unixsk_standalone we have check that means
"if socket have peer and that peer is GHOST and that peer fle->stage < FLE_OPEN"
return "try again". Ok. So, this task will stay on wait_fds_event().
2. Second task, that holds *peer* tried to open peer socket fd. So,
it also calls open_fd() -> open_unixsk_standalone() -> opening socket
-> bind_unix_sk() -> in bind_unix_sk we have call to wake_connected_sockets().
So, after that call we will "wake up" task from first point and it may proceed
fd restoring. Yes? No. In first point we need to "peer_fle->stage >= FLE_OPEN"
but fle->stage of our peer socket will become FLE_OPEN in open_fd(). After we
return from open_unixsk_standalone we proceed to setup_and_serve_out() where we have
appropriate stage change.
Between call of wake_connected_sockets and moment when we set stage to FLE_OPEN
should pass very small amount of time. But it may happen, so we "wake up"
tasks that holds client sockets but did not have enough time to change fle->stage
to FLE_OPEN. Exactly that case I've managed to reproduce.
(Really, ossec-hids application managed to reproduce this problem at first %) )
v1: file_desc_ops->on_stage_change callback was introduced,
sk-unix ghost code reworked so that to call wake_connected_sockets() strictly
after changing fle->stage to FLE_OPEN.
v2: implementation replaced with short and more practical patch by Andrei
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
On modern Linux distributions iptables binaries using new nftables
API. We dump iptables rules using "iptables-save", and nftables
rules using libnftables API. This breaks network unlock on modern systems
because technically, we dump rules (including network lock rules) two times.
There is another problem - on host we can have modern distribution, but
in Docker container we can use iptables with netfilter (legacy) API.
So, in this case this legacy rules will be skipped.
This patch handles all of that cases. It tries to find iptables legacy and
dump legacy rules by using appropriate iptables binaries, dump nftables
rules by using libnftables.
Fixes#1435
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
CRIU used to check for the existence of /sys/fs/selinux to see if
SELinux is enabled on a system. We have seen systems with SELinux kind
of enabled but reading out the labels gives does not return real labels.
To work around this, this commit adds a check during LSM detection
if SELinux labels are in the right format. For CRIU this check means to
see if there are at least 3 ':' in a label. If not CRIU switches to no
LSM mode.
Signed-off-by: Adrian Reber <areber@redhat.com>
As of January 1st, 2020 Python 2 is no longer supported and
many distributions no longer provide packages for Python 2
dependencies.
This patch allows CRIU to use Python 3 by default when both
major versions are available on the system.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
CRIU follows Linux kernel coding style. This patch updates the
architecture-specific code for MIPS to use tab indentation,
add whitespace between closing parenthesis and open bracket,
and changes the mode of source files from 755 to 644.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
When invoking an action-script, all file descriptors >= 3 are closed.
If execvp() fails, we can only log the error on stderr. pr_msg() outputs
on stderr, so we use this as opposed to pr_perror().
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Unlike pr_perror, pr_err and other macros do not append \n
to the message being printed, so the caller needs to take care of it.
Sometimes it was not done, so let's add this manually.
To make sure it won't happen again, add a line to Makefile under the
linter target to check for such missing \n. NOTE this check is only
done for part of such cases (where the pr_* statement fits in one line
and there's no comment after), but it's better than nothing.
Add comments after pr_msg and pr_info statements where we deliberately
don't add \n, so that the above check ignores them.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
My editor (vim) auto-removes whitespace at EOL for *.c and *.h files,
and I think it makes sense to have a separate commit for this, rather
than littering other commits with such changes.
To make sure this won't pile up again, add a line to Makefile under
the linter target to check for such things (so CI will fail).
This is all whitespace except an addition to Makefile.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1. Use pr_perror where errno needs to be shown.
2. Use pr_err in cases where errno is not set
by the previous failed call.
3. Make sure pr_err's first argument do not have \n.
4. While at it, fix some error messages.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
On my system (shellcheck v0.7.1) make lint shows a few warnings about
needing to quote variables.
Fix those.
PS I am not sure why those are not shown by GHA CI, I assume there is
different shellcheck version used. Add shellcheck -- version to the
appropriate Makefile target to avoid confusion.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
In many cases developers forget that pr_perror and fail macros
are a bit special, in particular:
1. they already show errno;
2. they already append \n to the message.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Macro fail() already prints the value of errno, so there's no need to
explicitly add it.
Found by git grep '^\s*\<fail\>.*errno'
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Macro fail already appends errno and strerror(errno) to the error
message, so there's no need to do it explicitly.
Brought to you by
for f in $(git grep -l fail test/zdtm); do
test -f $f || continue
echo $f
sed -i '\|^[[:space:]]*fail(.*[ (]%m)*"|s/:*[ (]*%m)*//' $f
done
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Macro fail already appends \n to the message, so there's no need to do
it explicitly.
Brought to you by
for f in $(git grep -l fail test/zdtm); do
test -f $f || continue
echo $f
sed -i '\%^[[:space:]]*fail(.*\\n"%s/\\n"/"/' $f
done
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Macro pr_perror already adds errno and its string representation to the
error message, so there's no need to explicitly do it.
While at it, fix some error messages.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
pr_perror should be used for cases where the failed operation sets
errno. For cases where errno is not set, pr_err is preferable.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Another pr_perror spring cleaning time!
As pr_perror adds a semicolon, an strerror(errno), and a newline,
there's no need to add one manually.
Brought to you by
for f in $(git grep -l pr_perror); do
test -f $f || continue
echo $f
sed -i '\%^[[:space:]]*pr_perror(.*\\n"%s/\\n//' $f
done
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Send an RTM_SETLINK request with a negative IFLA_NEW_IFINDEX. If
IFLA_NEW_IFINDEX is supported, the kernel will return ERANGE.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Running zdtm tests does not require input and therefore it is not
necessary to use -it. This change also allows to run the test in CI
where it currently fails with:
the input device is not a TTY
make: *** [Makefile:388: docker-test] Error 1
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
All zdtm tests pass on Fedora 33 for `make docker-build && make docker-test`
with devicemapper storage driver.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The test/zdtm_mount_cgroups script fails with 'permission denied'
when running tests with private cgroup namespace.
Using the host network namespace allows us to test criu as if
it is running on the host, sharing iptables rules etc.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
In order to be able to run the zdtm tests inside a container,
we have to make sure that all protobuf sources have been compiled.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The 'make docker-build' command creates a copy of all files from the
in local CRIU clone inside a container.
Then it runs 'make mrproper' inside the container, followed by
compilation of criu, followed by another 'make mrproper'.
After the last mrproper command, it attempts to check if
the clean was successful by running 'git clean'.
However, this check fails when the local repository contains
files that are not part of the repository.
For example, the vscode editor creates the folder '.vscode/'
which would be copied inside the docker container and cause
'make docker-build' to fail.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
return value of is_empty_dir:
* < 0 : open directory stream failed
* 0 : directory is not empty
* 1 : directory is empty
Signed-off-by: Liu Hua <weldonliu@tencent.com>
This introduces a new option
--external netdev[IFNAME]:ORIGNAME
which informs CRIU that this is pre-created network device that it is
supposed to move into a target network namespace. The "netdev" name was
chosen to make it flexible enough to e.g. also cover physical devices if
that is desirable at some point. For example:
--external netdev[eth0]:vethA23adf3
would instruct CRIU to move the network device with the name
"vethA23adf3" into a target network namespace renaming it to "eth0"
while doing so.
In order to restore ip addresses and additional data correctly CRIU
needs to move the network device into the target netns with the recorded
ifindex. This requires a kernel patch as discussed in [1]. The patch has
been merged into net-next and is expected to show up in the v5.13
release (cf. [2])
The motivating use-case can be found in [1]. But I'm repeating it mostly
verbatim here:
Assume a container with a standard veth tunnel for an unprivileged container:
<veth-host> <-> <bridge-host> <-> <veth-container>
When LXD starts a container it will create the veth pair in the host
namespaces with random names, let's assume:
<veth-host> := vethHOST
<veth-container> := vethCONT
The LXD generates a config for the container and tells the container to
use vethCONT as network device and usually also tells it to rename that
device to something more sensible like eth3. The container will then use
netlink to move and rename the vethCONT device into it's network
namespace as eth3 during startup.
Users may use lxc snapshot --stateful to create a CRIU dump.
And they can restore via
lxc restore --stateful <container-name> <stateful-snapshot-name>
And this is where things get hairy currently. LXD's network models
requires it to always be in control of all network devices and so
similar to regular startup it will precreate the two veth devices
vethHOST and vethCONT and tell LXC about it.
What we would like CRIU to be able to do is to add a commandline option
to tell CRIU to not bother creating the veth device but instead to
simply assume that someone else will create, move, and rename it and
instead just restore routes, iptables, addresses and so on.
With this kernel patch applied I can successfully dump and restore a
LXD containers:
ubuntu@f2-vm:~/src/bin$ lxc launch images:alpine/edge alp1
Creating alp1
Starting alp1
ubuntu@f2-vm:~/src/bin$ lxc snapshot --stateful alp1
ubuntu@f2-vm:~/src/bin$ lxc list
+------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| alp1 | RUNNING | 10.47.211.144 (eth0) | fd42:8722:277d:69cf:216:3eff:fe69:9b8b (eth0) | CONTAINER | 1 |
+------+---------+----------------------+-----------------------------------------------+-----------+-----------+
ubuntu@f2-vm:~/src/bin$ lxc restore --stateful alp1 snap0
ubuntu@f2-vm:~/src/bin$ lxc list
+------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| alp1 | RUNNING | 10.47.211.144 (eth0) | fd42:8722:277d:69cf:216:3eff:fe69:9b8b (eth0) | CONTAINER | 1 |
+------+---------+----------------------+-----------------------------------------------+-----------+-----------+
ubuntu@f2-vm:~/src/bin$ lxc exec alp1 -- sh
~ # ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
15: eth0@if18: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 00:16:3e:69:9b:8b brd ff:ff:ff:ff:ff:ff
inet 10.47.211.144/24 brd 10.47.211.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fd42:8722:277d:69cf:216:3eff:fe69:9b8b/64 scope global dynamic flags 100
valid_lft 86355sec preferred_lft 86355sec
inet6 fe80::216:3eff:fe69:9b8b/64 scope link
valid_lft forever preferred_lft forever
[1]: https://github.com/checkpoint-restore/criu/issues/1421
[2]: https://patchwork.kernel.org/project/netdevbpf/patch/20210406075448.203816-1-avagin@gmail.com/Fixes: #1421
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
The ENV1 variable was first introduced with commit
7290de5 (travis: enable ccache for docker/qemu builds)
and it is not used anymore.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <minhquangbui99@gmail.com>
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 <zeyady98@gmail.com>
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 <areber@redhat.com>
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 <ptikhomirov@virtuozzo.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This change extracts some of the duplicated code from
set_pidns() and set_mntns() functions.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
This test should be run with at least 1 pre-dump to trigger the problem as mentioned in commit 4d9bf608b5.
Signed-off-by: Zeyad Yasser <zeyady98@gmail.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <module>
> 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 <dima@arista.com>
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 <rstoyanov@fedoraproject.org>
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 <ptikhomirov@virtuozzo.com>
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 <areber@redhat.com>
This reverts commit c98af78c58.
Now FPU/SSE/MMX/etc can be used inside parasite.
Let's have compiler optimizations back.
Cc: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Arch-dependend way to restore extended registers set.
Use it straight-away to restore per-thread registers.
Signed-off-by: Dmitry Safonov <dima@arista.com>
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 <dima@arista.com>
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 <dima@arista.com>
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 <dima@arista.com>
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 <ptikhomirov@virtuozzo.com>
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 <dima@arista.com>
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 <areber@redhat.com>
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 <ptikhomirov@virtuozzo.com>
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 <avagin@gmail.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <Nicolas.Viennot@twosigma.com>
This differs from the previous one by
1. using relative path instead of absolute
2. chdir() after setup
Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
Create unix socket and unlink it. Make fifo in this place.
Reviewed-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
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 <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
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 <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
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 <alexander.mikhalitsyn@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrey Zhadchenko <andrey.zhadchenko@virtuozzo.com>
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 <gorcunov@virtuozzo.com>
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 <avagin@gmail.com>
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 <avagin@gmail.com>
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 <luolongjuna@gmail.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <ptikhomirov@virtuozzo.com>
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 <areber@redhat.com>
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 <andrey.zhadchenko@virtuozzo.com>
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 <andrey.zhadchenko@virtuozzo.com>
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 <andrey.zhadchenko@virtuozzo.com>
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 <avagin@gmail.com>
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 <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
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 <areber@redhat.com>
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 <ptikhomirov@virtuozzo.com>
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 <ptikhomirov@virtuozzo.com>
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 <ptikhomirov@virtuozzo.com>
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 <rstoyanov@fedoraproject.org>
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 <rstoyanov@fedoraproject.org>
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: dd71cca58a ("dump/x86: sanitize the ERESTART_RESTARTBLOCK -> EINTR transition")
Signed-off-by: Andrei Vagin <avagin@gmail.com>
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 <areber@redhat.com>
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 <avagin@gmail.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <ptikhomirov@virtuozzo.com>
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 <luolongjuna@gmail.com>
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 <avagin@gmail.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
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 <ptikhomirov@virtuozzo.com>
---
v2: add new external_pidns variable to sinchronize all uses of external
pidns case
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 <ptikhomirov@virtuozzo.com>
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 <ptikhomirov@virtuozzo.com>
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 <ptikhomirov@virtuozzo.com>
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 <tim.gates@iress.com>
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 <ptikhomirov@virtuozzo.com>
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 <rppt@linux.ibm.com>
Currently the code checks for SIGSTOP only if (!current).
Let's provide better status checks for debug-ability.
Signed-off-by: Dmitry Safonov <dima@arista.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <rstoyanov@fedoraproject.org>
%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 <dima@arista.com>
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 <dima@arista.com>
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 <dima@arista.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <rstoyanov@fedoraproject.org>
The special characters in the test selection regexp should no be esaped
for the regexp to work properly.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <areber@redhat.com>
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 <mclapinski@google.com>
When criu restore runs as PID=1 it has an additional responsibility to
reap zombie processes.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
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 <rstoyanov@fedoraproject.org>
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 <rstoyanov1@gmail.com>
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 <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
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 <xemul@virtuozzo.com>
Looks-good-to: Andrey Vagin <avagin@openvz.org>
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 <areber@redhat.com>
This is yet another big release with many new features in it:
* Introduced criu-image-streamer
* Added MIPS support.
* Allow checkpointing out of existing PID namespace and
restoring into existing PID namespace.
* Added additional file validation mechanisms
* Added support to checkpoint and restore BPF hash maps and array maps.
* Initial cgroup2 support
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Build on Fedora Core 33 produces the following warnings:
include/common/asm/bitops.h: Assembler messages:
include/common/asm/bitops.h:37: Warning: no instruction mnemonic suffix given and no register operands; using default for `bt'
include/common/asm/bitops.h: Assembler messages:
include/common/asm/bitops.h:63: Warning: no instruction mnemonic suffix given and no register operands; using default for `bts'
Update test_bit() and test_and_set_bit() implementation with recent
version from the Linux kernel to fix the warning.
Fixes#1217
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
GNU ld precalculates this information but lld does not. With this
change, handle-elf.c calculates those addresses on its own.
When calculating addresses sections with SHF_ALLOC bit are put one after
another, respecting their alignment requirements. This matches the way
how the blob is constructed by copying section contents.
Signed-off-by: Wojciech Marczenko <marczenko@google.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
CID 73358 (#1 of 1): Improper use of negative value (NEGATIVE_RETURNS)
sk is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 181217 (#1 of 1): Explicit null dereferenced (FORWARD_NULL)
Passing null pointer mntns to mntns_get_root_fd, which dereferences it.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 192968 (#1 of 1): Improper use of negative value (NEGATIVE_RETURNS)
dup(fd) is passed to a parameter that cannot be negative. [show details]
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 73358 (#2 of 2): Argument cannot be negative (NEGATIVE_RETURNS)
sk is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 73378 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
sk is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 92720 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
pfd is passed to a parameter that cannot be negative.
CID 92747 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
pfd is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 178391 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
sk is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 192961 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
sockfd is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 192963 (#1 of 1): Improper use of negative value (NEGATIVE_RETURNS)
dup(sk) is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226477 (#1 of 1): Resource leak (RESOURCE_LEAK)
Variable fd_dir going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226478 (#1 of 2): Double close (USE_AFTER_FREE)
Calling close(int) closes handle fd which has already been closed.
CID 226478 (#2 of 2): Double close (USE_AFTER_FREE)
Calling close(int) closes handle fd which has already been closed.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226480 (#1 of 1): Copy into fixed size buffer (STRING_OVERFLOW)
You might overrun the 4096-character fixed-size string root_link.name by copying new->root without checking the length.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226482 (#1 of 1): Resource leak (RESOURCE_LEAK)
Variable path going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226483 (#1 of 1): Resource leak (RESOURCE_LEAK)
Variable p going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226484 (#1 of 1): Double close (USE_AFTER_FREE)
Calling close(int) closes handle fd which has already been closed.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226485 (#1 of 3): Resource leak (RESOURCE_LEAK)
Variable events going out of scope leaks the storage it points to
CID 226485 (#2 of 3): Resource leak (RESOURCE_LEAK)
Variable events going out of scope leaks the storage it points to
CID 226485 (#3 of 3): Resource leak (RESOURCE_LEAK)
Variable events going out of scope leaks the storage it points to
Also changed epoll_prepare() to check return value of epoll_create()
against '< 0' instead if '== -1' to make coverity happy.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 226486 (#1 of 2): Resource leak (RESOURCE_LEAK)
Variable mi going out of scope leaks the storage it points to.
CID 226486 (#2 of 2): Resource leak (RESOURCE_LEAK)
Variable mi going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302711 (#1 of 1): Logically dead code (DEADCODE)
Execution cannot reach the expression pr->io_complete inside this statement: if (ret == 0 && pr->io_comp....
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302712 (#1 of 1): Resource leak (RESOURCE_LEAK)
Variable build_id going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302714 (#1 of 1): Resource leak (RESOURCE_LEAK)
Variable dirnew going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302715 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
fd is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302717 (#2 of 2): Resource leak (RESOURCE_LEAK)
Variable dirnew going out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302718 (#1 of 1): Double close (USE_AFTER_FREE)
Calling close(int) closes handle sockfd which has already been closed.
Signed-off-by: Adrian Reber <areber@redhat.com>
CID 302719 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
img_raw_fd(img) is passed to a parameter that cannot be negative.
Signed-off-by: Adrian Reber <areber@redhat.com>
This commit achieves the following:
a) Refactors ZDTM tests bpf_array.c and bpf_hash.c to make use of the
BPF ZDTM library functions. In addition, these tests now verify whether
information obtained from both procfs and BPF_OBJ_GET_INFO_BY_FD are
the same before and after c/r.
b) Updates ZDTM tests bpf_array.c and bpf_hash.c to include a BPF map's
name and also to freeze maps
Source files modified:
* zdtm/static/bpf_array.c
* zdtm/static/bpf_hash.c
Source files added:
* zdtm/static/bpf_array.desc
* zdtm/static/bpf_hash.desc
Note: ${test_name}.desc files have the 'suid' flag set because
BPF_MAP_FREEZE requires the global (root-userns) CAP_SYS_ADMIN or
CAP_BPF. Hence, only test flavors 'h' and 'ns' are executed ('uns'
is skipped) because BPF_MAP_FREEZE can't be used from non-root user
namespaces.
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit achieves the following:
a) C/R of a BPF map's name as well as ifindex (index of the network
interface to which the map is attached). This information is not
available from procfs and therefore has to be obtained using the
bpf() system call with BPF_OBJ_GET_INFO_BY_FD.
b) Adds support for frozen maps - during the restore operation, CRIU
now freezes a BPF map that was frozen during checkpoint.
Source files modified:
* bpfmap.c
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit adds a BPF map's name and ifindex to its protobuf image.
ifindex is the index of the network interface to which the BPF map is
attached and can be specified via a parameter while creating the BPF
map (BPF_MAP_CREATE). This commit also provides a default value of
false to the field 'frozen'.
Source files modified:
* images/bpfmap-file.proto
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit adds BPF helper functions needed by tests in a new library.
It defines new functions that allow verifying BPF map meta-data from
the procfs as well as using the bpf() system call with
BPF_OBJ_GET_INFO_BY_FD. It is necessary to verify from procfs and using
BPF_OBJ_GET_INFO_BY_FD because the information available from both
these places is disjoint (for example, checking whether a map is frozen
cannot be performed with BPF_OBJ_GET_INFO_BY_FD).
Source files modified:
* test/zdtm/lib/Makefile - Generating build artifacts
Source files added:
* test/zdtm/lib/bpfmap_zdtm.c - Provides definitions for 3 new
functions:
(a) parse_bpfmap_fdinfo() - Parses information about the BPF map
from procfs
(b) cmp_bpf_map_info() - Compares the attributes of a BPF map file
obtained from BPF_OBJ_GET_INFO_BY_FD. This function is typically
used to verify that the attributes of a BPF map remain the same
before checkpoint and after restore
(c) cmp_bpfmap_fdinfo() - Compares the attributes of a BPF map file
obtained from procfs. This function is typically used to verify
that the attributes of a BPF map remain the same before checkpoint
and after restore
* test/zdtm/lib/bpfmap_zdtm.h - Structure and function declarations.
Declares struct bpfmap_fdinfo_obj, which stores information about BPF
maps parsed from procfs
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
We can have tmp != sfd if fcntl(F_DUPFD) sees that sfd is already used,
but tmp is left open on this error path, lets close it.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
If the tcp-close has been set for dump, it has to set for restore too.
But we don't need to require matching of tcp-close for criu lazy-pages.
Reported-by: Mr Travis
There is no direct way to get this state but we can get polling events
for a socket and guess its shutdown state.
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The github action based cross compile tests are only running when
pushing to master or criu-dev. This changes this to have it run on all
branches. Useful to have all CI tests running on personal CRIU checkouts
on branches with other names.
If I prepare a branch to create a new pull request, the cross compile
tests have not been running if my branch has another name than criu-dev
or master. With this change these tests will run on all branches.
Signed-off-by: Adrian Reber <areber@redhat.com>
The previously introduced apt_install loop function to make package
install more robust against network errors is now moved to its own
script used in multiple places.
Signed-off-by: Adrian Reber <areber@redhat.com>
Shellcheck (https://github.com/koalaman/shellcheck) can identify common
errors in shell scripts. This initial integration of shellcheck only
checks the scripts in the 'scripts/' folder. This commit fixes (or
disables) all reports of shellcheck to ensure this part starts error
free. I am not convinced this is really necessary as most changes do not
seem to be necessary for their circumstances. On the other hand it
probably does not hurt to use a checker to avoid unnecessary errors.
Signed-off-by: Adrian Reber <areber@redhat.com>
In this case, states of established tcp connections will not be dumped
and they will not be blocked. This will be useful in case of snapshots,
when we don't need to restore tcp connections.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The SO_LINGER option allows to control how a TCP connection is closed.
The default behavior is to return immediately when close() is called,
and any unsent data is not guaranteed to be delivered. When SO_LINGER
is enabled, the close() call would block until all final data is
delivered to the remote end, for a specified time interval. When the
time interval is set to zero, the connection is aborted and any pending
data is immediately discarded upon close().
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
This patch enables checkpoint/restore of the SO_OOBINLINE socket option.
When the SO_OOBINLINE option is used, out-of-band data is placed in the
normal input queue as it is received. This permits it to be read using
read or recv without specifying the MSG_OOB flag.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Make two mounts, binds of the same file system, the first has root "/"
and the second has a cut root "/auxiliary". This insures that on restore
criu will mount the first mount first and latter bind the second from
it. After set the first mount unbindable to check if restoring these
flag does not interfere with restoring mounts.
Before the fix in these series we had the error:
(00.031286) 1: mnt: Mounting tmpfs @/tmp/.criu.mntns.wGroPU/12-0000000000/zdtm/static/unbindable.test/bind_of_unbindable (0)
(00.031298) 1: mnt: Bind /tmp/.criu.mntns.wGroPU/12-0000000000/zdtm/static/unbindable.test/unbindable/auxiliary to /tmp/.criu.mntns.wGroPU/12-0000000000/zdtm/static/unbindable.test/bind_of_unbindable
(00.031329) 1: Error (criu/mount.c:2298): mnt: Can't mount at /tmp/.criu.mntns.wGroPU/12-0000000000/zdtm/static/unbindable.test/bind_of_unbindable: Invalid argument
https://bugs.openvz.org/browse/OVZ-7116
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Replace in restore_shared_options "->mountpoint" in messages with more
descriptive "->mnt_id". Mountpoints concide a lot, and mnt_id is unique.
These also makes a message shorter. (We already print a mapping from
mnt_id to mountpoint in mnt_tree_show, so we can easily find mountpoint
if we want).
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Setting mounts unbindable just after mounting them and before other
mounts of the same superblock are mounted can break the restore of
mounts, because other mounts will try to bind from it and obviously will
fail. See the test "unbindable" for more info.
Currently we can't delay if the mount is overmounted, if we will
need these in future we would likely set it through open fd on the
mountpoint.
https://bugs.openvz.org/browse/OVZ-7116
v2: simplify coderead, print message on setting unbindable error, add
some more comments about unbindable.
v3: add a list to optimise a walk over delayed unbindable mounts, don't
call set_unbindable on error path.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Netlink sockets normally kernel-assign a peer id based on the
requesting pid at bind time. CRIU saves this peer ID and tries
to restore it. At restore time, it's possible for the id to
already be in use (e.g., assigned to another process, perhaps
in another pid namespace).
This patch tries to use the original id, but if that fails then
allows the kernel to auto-allocate a new peer id. We make a
warning message, because it is possible (although rather unlikely)
the application cares what its peer id is.
Signed-off-by: Radostin Stoyanov <rstoyanov@fedoraproject.org>
The field id 18 is used in Virtuozzo criu in multiple releases, so that
we can't change the id easily. So we can at least kindly ask not to use
this field in mainstream criu to decrease the pain of Virtuozzo criu
rebases.
Reference to related patch in Virtuozzo criu:
https://src.openvz.org/projects/OVZ/repos/criu/commits/58e61a20c22c#images/sk-unix.proto
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
This adds three epoll targets on tfd 702 and then adds two epoll targets
on tfd 701. This test is for off calculation in dump_one_eventpoll, the
reverse order makes qsort to actually work.
v2: update test_doc with longer explanation, remove unused DUPFDNO
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Kcmp expect off to be a number of inclusion of target tfd. So we should
set off=0 to a first inclusion and off++ for all next inclusions.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In dump_one_eventpoll we call find_tfd_bsearch with arguments
"e->tfd[i]->tfd, toff[i].off". By this we want to check if
"toff[i].off"-th inclusion of target "e->tfd[i]->tfd" in an eventpoll
coresponds to our fd "e->tfd[i]->tfd" in terms of kcmp.
But because of toff was sorted to calculate off, indexes in e->tfd and
toff does not address the same eventpoll target at this point.
Let's sort toff back to original state to make indexes consistent.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The docker hub container registry is not updated as fast as Fedora's
registry at registry.fedoraproject.org. Fedora's registry gets a new
image whenever there is a new version of rawhide, docker hub's rawhide
image can take a couple of weeks because the process is not automated.
Especially when Fedora branches of a new release we see lot's of errors
in CRIU's Fedora rawhide based Travis runs. Switch to Fedora's registry
to always have the newest rawhide images for our tests.
Signed-off-by: Adrian Reber <areber@redhat.com>
Since commit cdd08cdff ("uffd: use userns_call() to execute
ioctl(UFFDIO_API)") UFFD_API ioctl() is wrapped with userns_call() and this
allows runing lazy-pages tests on recent kernels in uns.
Restore testing of lazy-pages in uns in travis.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
This commit adds ZDTM tests for c/r of processes with BPF maps as open
files
Source files added:
* zdtm/static/bpf_hash.c - Tests for c/r of the data and meta-data of
BPF map type BPF_MAP_TYPE_HASH
* zdtm/static/bpf_array.c - Tests for c/r of the data and meta-data
of BPF map type BPF_MAP_TYPE_ARRAY
Source files modified:
* zdtm/static/Makefile - Generating build artifacts for BPF tests
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit restores the data of BPF maps. A hash table (indexed by
the map's id) is used to store data objects for multiple BPF map
files that a process may have opened. Collisions are resolved with
chaining using a linked list.
Source files modified:
* bpfmap.c - Structure and function definitions needed to:
(a) collect the protobuf image containing BPF map data
(b) read the BPF map's data from the image and store it in the
hash table
(c) restore the map's data using bpf_map_update_batch()
* include/bpfmap.h
- Defines the size of the hash table and maks to be used while
indexing into it
- Structure and function declarations that are used while restoring
BPF map data
* cr-restore.c - Collects the protobuf image containing BPF map data
during the restoration phase
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit enables CRIU to restore a process' BPF map file
descriptors.
Source files modified:
* bpfmap.c - Structure and function definitions needed to:
(a) collect a BPF map's information from its protobuf image
(b) create and open a BPF map with the same parameters as when
it was dumped
(c) add the newly opened BPF map to the process' file descriptor
list
* include/bpfmap.h - Structure declarations for restoring BPF maps
* files.c - Collects a BPF map's file entry during the restoration
phase
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit enables CRIT to decode the contents of a protobuf image
that stores information related to BPF map
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit enables CRIU to dump data(key-value) pairs stored in BPF
maps
Source files modified:
* bpfmap.c
- Function dump_one_bpfmap_data() reads the map's keys and
values into two buffers using bpf_map_lookup_batch() and then
writes them out to a protobuf image along with the number of
key-value pairs read
- Function dump_one_bpfmap() now dumps the data as well before
returning
* include/bpfmap.h - Includes headers and declares functions needed to
dump BPF map data
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit enables CRIU to dump meta-data about BPF maps files by
prividing the structures and functions needed by other parts of the
code-base.
Source files added:
* bpfmap.c - defines new structures and functions:
(a) struct fdtype_ops bpfmap_dump_ops:
sets up the function handler to dump BPF maps
(b) is_bpfmap_link():
checks whether an anonymous inode is a BPF map file
(c) dump_one_bpfmap():
parses information for a BPF map file from procfs and
dumps it
* include/bpfmap.h - structure and function declarations
Source files modified:
* Makefile.crtools - generates build artifacts for bpfmap.c
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit enables CRIU to:
(a) identify an anonymous inode as being a BPF map
(b) parse information about BPF maps from procfs
Source files modified:
* files.c - Checks anonymous inodes to see whether they are BPF maps.
If so, sets struct fdtype_ops *ops to a structure that knows how to
dump BPF maps
* proc_parse.c - Function parse_fdinfo_pid_s() now checks whether the
current file being processed is a BPF map. If so, it calls a newly
defined function parse_bpfmap() which knows how to parse information
about BPF maps from procfs
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
Source files modified:
* Makefile.config - Checks whether libbpf is installed on the system.
If so, we add -lbpf to LIBS_FEATURES, -DCONFIG_HAS_LIBBPF to
FEATURE_DEFINES and set CONFIG_HAS_LIBBPF. This allows us to check for
the presence of libbpf before compiling or executing BPF c/r code and
ZDTM tests.
* Makefile - Set CONFIG_HAS_LIBBPF to clean all files.
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit defines constants and includes necessary headers to c/r
BPF maps
Source files modified:
* magic.h - Defining BPFMAP_FILE_MAGIC and BPFMAP_DATA_MAGIC
* image-desc.h - Defining CR_FD_BPFMAP_FILE and CR_FD_BPFMAP_DATA
* image-desc.c - Create new entries for bpfmap-file and bpfmap-data
in CRIU's file descriptor set
* protobuf-desc.h - Defining PB_BPFMAP_FILE and PB_BPFMAP_DATA
* protobuf-desc.c - Including headers for BPF map protobuf images
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
This commit adds protobuf definitions needed to checkpoint and
restore BPF map files along with the data they contain
Source files added:
* bpfmap-file.proto - Stores the meta-data about BPF maps
* bpfmap-data.proto - Stores the data (key-value pairs) contained
in BPF maps
Source files modified:
* fdinfo.proto - Added BPF map as a new kind of file descriptor.
'message file_entry' can now hold information about BPF map file
descriptors
* Makefile - Now generates build artifacts for bpfmap-file.proto
and bpfmap-data.proto
Signed-off-by: Abhishek Vijeev <abhishek.vijeev@gmail.com>
Master branch does not have mips support yet, so automated builds for
mips on the master branch fail.
Temporarily split mips cross-build into a separate files until mips
support will be mergded into the master branch.
Suggested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
This adds a definition to do a daily rebuild of all cross-compile tests
on the master and criu-dev branch.
Signed-off-by: Adrian Reber <areber@redhat.com>
One of the most common CI errors we see is that package install fails
due to some hashsum mismatch or some DNS errors.
This adds a loop around each apt-get install call to do a clean, update
and install and if one of the steps fails it repeats it up to 10 times.
Signed-off-by: Adrian Reber <areber@redhat.com>
I always wondered why re-running make on a criu checkout always prints
out
GEN magic.py
even if no file has changed. It seems the Makefile was looking for the
file in the wrong location. Providing the full path to the file will now
only rebuild magic.py if something actually changed that requires a
rebuild.
Signed-off-by: Adrian Reber <areber@redhat.com>
Fixes#1165
Traceback (most recent call last):
File "../criu/crit/crit-python3", line 6, in <module>
cli.main()
File "/home/xcv/repos/criu/crit/pycriu/cli.py", line 410, in main
opts["func"](opts)
File "/home/xcv/repos/criu/crit/pycriu/cli.py", line 43, in decode
json.dump(img, f, indent=indent)
File "/usr/lib/python3.8/json/__init__.py", line 179, in dump
for chunk in iterable:
File "/usr/lib/python3.8/json/encoder.py", line 431, in _iterencode
yield from _iterencode_dict(o, _current_indent_level)
File "/usr/lib/python3.8/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/usr/lib/python3.8/json/encoder.py", line 325, in _iterencode_list
yield from chunks
File "/usr/lib/python3.8/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/usr/lib/python3.8/json/encoder.py", line 405, in _iterencode_dict
yield from chunks
File "/usr/lib/python3.8/json/encoder.py", line 438, in _iterencode
o = _default(o)
File "/usr/lib/python3.8/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type bytes is not JSON serializable
Co-authored-by: Julian <jb@futureplay.de>
Signed-off-by: Otto Bittner <otto-bittner@gmx.de>
The description of the Fixes: tags could be misleading and may be
understood as if "Fixes: " should be the commit summary.
Add a sentence with explicit description of Fixme: tags placement.
Reported-by: Otto Bittner <otto-bittner@gmx.de>
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
When using libcriu with the notify callback functionality CRIU transmits
an FD during 'orphan-pts-master' back to libcriu user. This is message
is sent via sendmsg() to transmit the FD and not via write() as all
other protobuf messages.
libcriu was using recv() and to be able to receive the FD this needs to
be changed to recvmsg() and if an FD is attached to it (currently only
for 'orphan-pts-master' this FD is stored in a variable which can be
retrieved with the function criu_get_orphan_pts_master_fd().
Signed-off-by: Adrian Reber <areber@redhat.com>
The decision whether a log message is info/warning/error should
be made by the place in code where it's shown, not by any other
expression. This makes it pointless to use the print_on_level
directly, as in each particular place the needed pr_foo() helper
can be chosen.
However, we cannot (easily) make this function static, so keep
it in header, but ask people to think twise (or more times) before
calling it directly.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
If a helper routine doesn't know whether its failure leads
to the error, then it should just emit a warning and return
-1. It's the caller who should print (or not) the error.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Instead of directly calling the print_on_level.
The pr_msg/pr_warn seems to be better choise for all those cases.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
This addresses a bug where the RegFileEntry n_build_id field would be
populated with incorrect data, causing dump to crash at times.
Signed-off-by: Ajay Bharadwaj <ajayrbharadwaj@gmail.com>
This addresses a bug when the ELF file contains multiple PT_NOTE program
headers but only the first header is checked for the build-id.
Signed-off-by: Ajay Bharadwaj <ajayrbharadwaj@gmail.com>
Previously, the GOT table was using the same memory location as the
args region, leading to difficult to debug memory corruption bugs.
We allocate the GOT table between the parasite blob and the args region.
The reason this is a good placement is:
1) Putting it after the args region is possible but a bit combersome as
the args region has a variable size
2) The cr-restore.c code maps the parasite code without the args region,
as it does not do RPC.
Another option is to rely on the linker to generate a GOT section, but I
failed to do so despite my best attempts.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
We don't need to push 0 on the stack. This seems to be a remnant of the
initial commit of 2011 that had a `pushq $0`.
The 16 bytes %rsp alignment was added with commit 2a0cea29 in 2012.
This is no longer necessary as we already guarantee that %rsp is 16
bytes aligned. A BUG_ON() is added to enforce this guarantee.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Previously, __export_parasite_cmd was located in parasite-head.S, and
__export_parasite_args located exactly at the end of the parasite blob.
This is not ideal for various reasons:
1) These two variables work together. It would be preferrable to have
them in the same location
2) This prevent us from allocating another section betweeen the parasite
blob and the args area. We'll need this to allocate a GOT table
This commit changes the allocation of these symbols from assembly/linker
script to a C file.
Moreover, the assembly entry points that invoke parasite_service()
prepares arguments with hand crafted assembly. This is unecessary.
This commit rewrite this logic with regular C code.
Note: if it wasn't for the x86 compat mode, we could remove all
parasite-head.S files and directly jump to parasite_service() via
ptrace. An int3 architecture specific equivalent could be called at the
end of parasite_service() with an inline asm statement.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
It is unnecessary and potentially confusing for understanding the memory
layout requirement of the parasite blob.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
It removes the potential confusion when it comes to virtual address vs
offsets. Further, doing so makes naming more consistent with the rest of
the parasite_blob_desc struct.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
compel_relocs_apply() was taking arguments mostly from the struct
parasite_blob_desc. Instead of passing all the arguments, we pass a
pointer to the struct itself.
This makes the code safer, as cr-restore.c calls compel_relocs_apply().
It previously needed to poke into what can be considered private
variables of the restorer-pie.h file.
To allow the parasite_blob_desc struct to be populated without a
parasite_ctl struct, we expand the compel API to export a
parasite_setup_c_header_desc() in the generated pie.h.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
COMMON symbols are emitted for global variable that are not initialized
in shared libraries.
They typically end up in the .bss section when linking an executable.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
This change is very straightforward. We don't skip the cgroup2
controller and dump it as any other controllers.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
I pushed the wrong branch to the pidns PR
https://github.com/checkpoint-restore/criu/pull/1056
which resulted in the wrong patches getting merged.
This is the actual result from the review.
Signed-off-by: Adrian Reber <areber@redhat.com>
file_validation_method field added to cr_options structure in
"criu/include/cr_options.h" along with the constants:
FILE_VALIDATION_FILE_SIZE
FILE_VALIDATION_BUILD_ID
FILE_VALIDATION_DEFAULT (Equal to FILE_VALIDATION_BUILD_ID)
Usage and description information is yet to be added
Usage:
--file-validation="filesize" (To use only the file size check)
--file-validation="buildid" (To try and use only the build-id check)
Signed-off-by: Ajay Bharadwaj <ajayrbharadwaj@gmail.com>
efi.h: Required for accessing the build-id of .efi files
This adds functions to find, store and compare with the stored build-id.
get_build_id() calls 32-bit or 64-bit helper functions depending on
the bitness of the ELF file after first ensuring that it is actually
an ELF file by checking for the magic number.
The number of iterations while searching the elf file for the
build-id before giving up (500 while searching the note section)
are limited.
Signed-off-by: Ajay Bharadwaj <ajayrbharadwaj@gmail.com>
This adds build-id, checksum, checksum-config and checksum-parameter fields
to RegFileEntry to store metadata used for file verification.
build_id: Holds the build-id if it could be obtained
checksum: Holds the checksum if it could be obtained
checksum_config: Holds the configuration of bytes for which checksum has
been calculated (The entire file, first N bytes or every Nth byte)
checksum_parameter: Specifies the value of 'N', if required, for the
configuration of bytes
Signed-off-by: Ajay Bharadwaj <ajayrbharadwaj@gmail.com>
When groups already have desired values, we skip calling setgroups.
Furthermore, this check allows us to restore when in an
unprivileged user namespace that cannot use setgroups.
Signed-off-by: Angie Ni <avtni@google.com>
Now that the new CRIU to criu-image-streamer protocol is in, we can use
the master branch of criu-image-streamer.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
CRIU sometimes returns 1 from main() with no explanation.
Changes made add more logging in the case of
initialization errors in config and crtools.
Signed-off-by: Angie Ni <avtni@google.com>
CRIU sometimes returns 1 from main() with no explanation.
These changes add additional logging for initialization errors in kerndat.
Signed-off-by: Angie Ni <avtni@google.com>
Adapt netns_ext tests to also work with pid namespaces and move it from
test/others/netns_ext/ to test/others/ns_ext/.
Also enable ns_ext tests in Travis runs.
Signed-off-by: Adrian Reber <areber@redhat.com>
This allows CRIU to restore a process into an existing PID namespace.
During checkpointing the PID namespace can be marked as external using:
--external pid[<inode>]:<label>
This can be the host PID namespace or any other PID namespace.
During restore a process can be restored into an existing PID namespace
using:
--inherit-fd fd[<FD>]:<label>
The <label> has to be the same for checkpoint and restore. CRIU uses
the <label> to know which resource the user means.
A process can start in the host PID namespace and can be moved to
another namespace or the other way around. Any PID namespace can be
used.
This is necessary to checkpoint containers in a POD which share certain
namespaces and this code to support external PID namespaces is the first
step towards checkpointing and restoring containers which belong to a
POD.
This is not using the --join-ns functionality as it is not possible to
move existing process to a PID namespace using setns(). Only child
process will be created in the PID namespace and that is why setns()
needs to be called before clone().
Signed-off-by: Adrian Reber <areber@redhat.com>
This loads and stores the key for an external PID namespace if specified
by the user using: --external pid[<inode>]:<label>
Preparation for restoring into existing PID namespaces.
Signed-off-by: Adrian Reber <areber@redhat.com>
Create a session leader and it's child - session member, make leader
zombie. To restore this criu will need to create a helper task a child
of our zombie so that member can inherit session. Before fixes in this
patchset we segfault on empty ids and fail to restore cgroups because of
empty cg_set
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In case if our parent is a dead task (zombie) or a helper which in it's
turn has zombie parent, and parent thus has zero cg_set we should look
for current cgset deeper.
Fixes: #1066
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In case if our parent is a dead task (zombie) we should lookup
for parent ids which will be inherited on restore. Otherwise
parent->ids may be nil and SIGSEGV produced.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Rework and port from vzcriu:
87b320964 ("vz7: mount: restore_task_mnt_ns - Lookup for mount namespace
conditionally")
Fixes: #1066
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
When uffd_open is called from kerndat_uffd, userfaultfd failure is not
considered an error, so the goal is to suppress the error message --
instead, we print this message as info.
If the function fails, it is the responsibility of the caller
to print the error message.
Signed-off-by: Angie Ni <avtni@google.com>
* Mark lowcase criu as code in the environment section
* Add missing brace around the reference to https://criu.org/Secrity
* Fixup an admolition block that GitHub cannot render
* Spelling fixups
* s/github/GitHub/g
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Import "How to submit patches" article from CRIU wiki and update its
format to match GitHub markdown.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
The layout of xsave frame in a standart format is predefined by the hardware.
Lets make sure we're increasing in frame offsets and use latest offset where
appropriate.
https://github.com/checkpoint-restore/criu/issues/1042
Reported-by: Ashutosh Mehra <mehra.ashutosh@ibm.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
TL;DR: this makes possible -v with criu swrk, and removes showing usage
which is useless in swrk mode.
1. Since criu swrk command is not described in usage, there is no sense
in showing it. Instead, show a one-line hint about how to use it.
2. In case some global options (like -v) are used, argv[1] might not
point to "swrk". Use optind to point to a correct non-option
argument.
3. While at it, also error out in case we have extra arguments.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This adds the minimal configuration to run Fedora 31 based VMs on
Travis.
This can be used to test cgroupv2 based tests, tests with vdso=off and
probably much more which requires booting a newer kernel.
As an example this builds CRIU on Fedora 31 and reconfigures it to boot
without VDSO support and runs one single test.
Signed-off-by: Adrian Reber <areber@redhat.com>
Without clone3() CRIU was able to detect a process with a wrong PID only
in the already created child process. With clone3() this error can
happen before the process is created.
In the case of EEXIST this error will now be correctly forwarded to an
RPC client.
This was detected by running test/others/libcriu on a clone3() system.
Signed-off-by: Adrian Reber <areber@redhat.com>
Although the CRIU version is exported in macros in version.h it only
contains the CRIU version of libcriu during build time.
As it is possible that CRIU is upgraded since the last time something
was built against libcriu, this adds functions to query the actual CRIU
binary about its version.
Signed-off-by: Adrian Reber <areber@redhat.com>
When we use swrk, we have a mechanism to send notifications over RPC.
It is cleaner and more straightforward than sending \0 to status fd.
For now, both mechanisms are supported, although status fd request
option is now deprecated, so a warning is logged in case it's used.
Guess we can remove it in a few years.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The name close_service_fd() is misleading, as it not just closes the
status_fd, but also writes to it. On a high level, though, it signals
the other side that we are ready, so rename to status_ready.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
7. criu-3.14/criu/timens.c:67: leaked_storage: Variable "img" going out of scope leaks the storage it points to.
65| if (id == 0 && empty_image(img)) {
66| pr_warn("Clocks values have not been dumped\n");
67|-> return 0;
68| }
Signed-off-by: Adrian Reber <areber@redhat.com>
The orphan pts master option was introduced with commit [1]
to enable checkpoint/restore of containers with a pty pair
used as a console.
[1] 6afe523d97
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
While working on runc checkpointing, I incorrectly closed status_fd
prematurely, and received an error from CRIU, but it was
non-descriptive.
Do print the error from open().
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The message "Overwriting RPC settings with values from <filename>" is
misleading, giving the impression that file is being read and consumed.
It really puzzled me, since <filename> didn't exist.
What it needs to say is "Would overwrite", i.e. if a file with such name
is present, it would be used.
Also, add actual "Parsing file ..." so it will be clear which files are
being used.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This moves the cross compilation tests to github actions, to slightly
reduce the number of Travis tests and run them in parallel on github
actions.
Signed-off-by: Adrian Reber <areber@redhat.com>
A few tests were still running on xenial because at some point they were
hanging. This switches now all tests to bionic except one docker test
which still uses xenial to test with overlayfs.
Signed-off-by: Adrian Reber <areber@redhat.com>
A similar one is already printed in check_options().
Before this patch:
> $ ./criu/criu -vvvvvv --deprecated --log-file=/dev/stdout xxx
> (00.000000) Turn deprecated stuff ON
> ...
> (00.029680) DEPRECATED ON
> (00.029687) Error (criu/crtools.c:284): unknown command: xxx
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
k_rtsigset_t is 16Bytes in mips architecture but not 8Bytes.
so blk_sigset_extended be added in TaskCoreEntry and ThreadCoreEntry for dumping
extern 8Bytes data in parasite-syscall.c, restore extern 8Bytes data in cr-restore.c
Signed-off-by: Guoyun Sun <sunguoyun@loongson.cn>
On MIPS CPUs with VIPT caches also has aliasing issues, just like ARMv6.
To overcome this issue, page coloring 0x40000 align for shared mappings was introduced (SHMLBA) in kernel.
https://github.com/torvalds/linux/blob/master/arch/mips/include/asm/shmparam.h
Related to this, zdtm test suites ipc.c shm.c shm-unaligned.c and shm-mp.c are passed.
Signed-off-by: Guoyun Sun <sunguoyun@loongson.cn>
We permanently have issues like this:
./test/jenkins/criu-iter.sh: 3: source: not found
It looks like a good idea to use one shell to run our jenkins scripts.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
criu-3.12/criu/net.c:2043: overwrite_var: Overwriting "img" in "img =
open_image_at(-1, CR_FD_IP6TABLES, 0UL, pid)" leaks the storage that
"img" points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
The print_data() function was part of the deprecated (and removed)
'show' action, and it was moved in util.c with the following commit:
a501b4804b
The 'show' action has been deprecated since 1.6, let's finally drop it.
The print_data() routine is kept for yet another (to be deprecated too)
feature called 'criu exec'.
The criu exec feature was removed with:
909590a355
Remove criu exec code
It's now obsoleted by compel library.
Maybe-TODO: Add compel tool exec action?
Therefore, now we can drop print_data() as well.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
One can pass --stream to zdtm.py for testing criu with image streaming.
criu-image-streamer should be installed in ../criu-image-streamer
relative to the criu project directory. But any path will do providing
that criu-image-streamer can be found in the PATH env.
Added a few tests to run on travis-ci to make sure streaming works.
We run test that are likely to fail. However, it would be good to once
in a while run all tests with `--stream -a`.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
This adds the ability to stream images with criu-image-streamer
The workflow is the following:
1) criu-image-streamer is started, and starts listening on a UNIX
socket.
2) CRIU is started. img_streamer_init() is invoked, which connects to the
socket. During dump/restore operations, instead of using local disk to
open an image file, img_streamer_open() is called to provide a UNIX pipe
that is sent over the UNIX socket.
3) Once the operation is done, img_streamer_finish() is called, and the
UNIX socket is disconnected.
criu-image-streamer can be found at:
https://github.com/checkpoint-restore/criu-image-streamer
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Instead of erroring, we should loop until we get the desired number of
bytes written, like regular I/O loops.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
When CRIU calls the ip tool on restore, it passes the fd of remote
socket by replacing the STDIN before execvp. The stdin is used by the
ip tool to receive input. However, the ip tool calls ftell(stdin)
which fails with "Illegal seek" since UNIX sockets do not support file
positioning operations. To resolve this issue, read the received
content from the UNIX socket and store it into temporary file, then
replace STDIN with the fd of this tmp file.
# python test/zdtm.py run -t zdtm/static/env00 --remote -f ns
=== Run 1/1 ================ zdtm/static/env00
========================= Run zdtm/static/env00 in ns ==========================
Start test
./env00 --pidfile=env00.pid --outfile=env00.out --envname=ENV_00_TEST
Adding image cache
Adding image proxy
Run criu dump
Run criu restore
=[log]=> dump/zdtm/static/env00/31/1/restore.log
------------------------ grep Error ------------------------
RTNETLINK answers: File exists
(00.229895) 1: do_open_remote_image RDONLY path=route-9.img snapshot_id=dump/zdtm/static/env00/31/1
(00.230316) 1: Running ip route restore
Failed to restore: ftell: Illegal seek
(00.232757) 1: Error (criu/util.c:712): exited, status=255
(00.232777) 1: Error (criu/net.c:1479): IP tool failed on route restore
(00.232803) 1: Error (criu/net.c:2153): Can't create net_ns
(00.255091) Error (criu/cr-restore.c:1177): 105 killed by signal 9: Killed
(00.255307) Error (criu/mount.c:2960): mnt: Can't remove the directory /tmp/.criu.mntns.dTd7ak: No such file or directory
(00.255339) Error (criu/cr-restore.c:2119): Restoring FAILED.
------------------------ ERROR OVER ------------------------
################# Test zdtm/static/env00 FAIL at CRIU restore ##################
##################################### FAIL #####################################
Fixes#311
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When saddr.ss_family is AF_INET6 we should cast &saddr to
(struct sockaddr_in6 *).
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The newest version of flake reports errors that variable names like 'l'
should not be used, because they are hard to read.
This changes 'l' to 'line' to make flake8 happy.
Signed-off-by: Adrian Reber <areber@redhat.com>
With the latest version of the alpine container image it seems that
alpine changed a few package names. This adapts the alpine container
to solve the travis failures.
Signed-off-by: Adrian Reber <areber@redhat.com>
When using zdtm.py with --tls it started to fail as the certificates
seem to have expired. Following commands have been used to re-generate
the certificate:
# Generate CA key and certificate
echo -ne "ca\ncert_signing_key" > temp
certtool --generate-privkey > cakey.pem
certtool --generate-self-signed \
--template temp \
--load-privkey cakey.pem \
--outfile cacert.pem
# Generate server key and certificate
echo -ne "cn=$HOSTNAME\nencryption_key\nsigning_key" > temp
certtool --generate-privkey > key.pem
certtool --generate-certificate \
--template temp \
--load-privkey key.pem \
--load-ca-certificate cacert.pem \
--load-ca-privkey cakey.pem \
--outfile cert.pem
rm temp cakey.pem
Without this tests will fail in Travis.
Signed-off-by: Adrian Reber <areber@redhat.com>
The long-tempting release with lots of new features on board.
We have finally the time namespace support, great improvment of
the pre-dump memory consumption, new clone3 support and many
more.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
When testing runc checkpointing, I frequently see the following error:
> Error (criu/mount.c:1107): mnt: Can't create a temporary directory: Read-only file system
This happens because container root is read-only mount.
The error here is not actually fatal since it is handled later
in ns_open_mountpoint() (at least since [1] is fixed), but it is shown
as error in runc integration tests.
Since it is not fatal, let's demote it to a warning to avoid confusion.
[1] https://github.com/checkpoint-restore/criu/issues/520
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Clock IDs in this file has been replaced by clock symbolic names.
Now it looks like this:
$ cat /proc/774/timens_offsets
monotonic 864000 0
boottime 1728000 0
Signed-off-by: Andrei Vagin <avagin@gmail.com>
First don't free pstree_item as they are allocated with shmalloc on
restore. Second always pstree_entry__free_unpacked PstreeEntry. Third
remove all breaks replacing them with implict goto err, so that it would
be easier to understand that we are on error path. Forth split out
code for reading one pstree item in separate function.
Sadly there is no much use in xfree-ing pi->threads because in case of
an error we still have ->threads unfreed from previous entries anyway.
But at least some cleanup can be done here.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Changed all the %u into %d.
Ideally, we should implement the %u format for parasite code.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
kerndat_socket_netns() is called twice. We keep the latter to avoid
changing the behavior.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
We should follow Linux Kernel Codding Style:
... the closing brace is empty on a line of its own, except in the cases
where it is followed by a continuation of the same statement, ie ... an
else in an if-statement ...
https://www.kernel.org/doc/html/v4.10/process/coding-style.html#placing-braces-and-spaces
Automaticly fixing with:
:!git grep --files-with-matches "^\s*else[^{]*{" | xargs
:argadd <files>
:argdo :%s/}\s*\n\s*\(else[^{]*{\)/} \1/g | update
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
In real life cases pipe_ino param could be larger that INT_MAX,
but in autofs_parse() function we using atoi function, that uses
4 byte integers. It's a bug.
Example of mount info from real case:
(00.508286) type autofs source /etc/auto.misc mnt_id 2824 s_dev 0x4b9 / @
./misc flags 0x300000 options fd=5,pipe_ino=3480845226,pgrp=95929,timeout=300,
minproto=5,maxproto=5,indirect
3480845226 > 2147483647 (32-bit wide signed int max value) => we have a problem
It causes a error:
(03.195915) Error (criu/pipes.c:529): The packetized mode for pipes is not supported yet
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
This commit introduces an optimization when rsti(t)->vma_io is empty.
This optimization allows streaming a non-seekable image as CR_FD_PAGES
is not reopened.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
When an image is opened but errored with a ENOENT error, the image is
still valid. Later on, do_pb_read_one() can fail and will invoke
image_name(). The image fd is EMPTY_IMG_FD (-404). read_fd_link fails.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
After restoring processes, we have to be sure that monotonic and
boottime clocks will not go backward. For this, we can restore processes
in a new time namespace and set proper offsets for the clocks.
In this patch, criu dumps clocks values event when processes are running
in this host time namespace and on restore, criu creates a new time
namespace, sets dumped clock values and restores processes.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This test checks that monotonic and boottime don't jump after C/R.
In ns and uns flavors, the test is started in a separate time namespace
with big offsets, so if criu will restore a time namespace incorrectly
the test will detect the big delta of clocks values before and after C/R.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The time namespace allows for per-namespace offsets to the system
monotonic and boot-time clocks.
C/R of time namespaces are very straightforward. On dump, criu enters a
target time namespace and dumps currents clocks values, then on restore,
criu creates a new namespace and restores clocks values.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Hope I have enough experience in the project to be nominated. I want to
help with review and will try to do my best in it.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Revert "util: introduce the mount_detached_fs helper"
This reverts commit 5dbc24b206.
Revert "criu: Make use strlcpy() to copy into allocated strings"
This reverts commit bc49927bbc.
Fixes for https://github.com/checkpoint-restore/criu/pull/1003
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The struct memfd_inode has a union for dump and restore parts.
The only common parts are the list_head node, and the inode id.
Suggested-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Per-object image is acceptable if we expect to have 1-3 objects
per-container. If we expect to have more objects, it is better to save
them all into one image. There are a number of reasons for this:
* We need fewer system calls to read all objects from one image.
* It is faster to save or move one image.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
After running make install, build directory is generated but not ignored
in gitignore. So this commit add build directory to gitignore.
Signed-off-by: Byeonggon Lee <gonny952@gmail.com>
Fix n_xid_map leaks on error path and remove useless exit_code.
Fixes: 6e1726f8 ("userns: set uid and gid before entering into userns")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The helper function removes code duplication from tests that want to
initialize unix socket address to an absolute file path, derived from
current working directory of the test + relative filename of a resulting
socket. Because the former code used cwd = get_current_dir_name() as
part of absolute filename generation, the resulting filepath could later
cause failure of bind systcall due to unchecked permissions and
introduce confusing permission errors.
Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Any filesystem syscall, that needs to navigate to inode by it's
absolute path performs successive lookup operations for each part of the
path. Lookup operation includes access rights check.
Usually but not always zdtm tests processes fall under 'other' access
category. Also, usually directories don't have 'x' bit set for other.
In case when bit 'x' is not set and user-ID and group-ID of a process
relate it to 'other', test's will not succeed in performing these
syscalls which are most of filesystem api, that has const char *path
as part of it arguments (open, openat, mkdir, bind, etc).
The observable behavior of that is that zdtm tests fail at file
creation ops on one system and pass on the other. The above is not
immediately clear to the developer by just looking at failed test's logs.
Investigation of that is also not quick for a developer due to the
complex structure of zdtm runtime where nested clones with
NAMESPACE flags take place alongside with bind-mounts.
As an additional note: 'get_current_dir_name' is documented as returning
EACCESS in case when some part of the path lacks read/list permissions.
But in fact it's not always so. Practice shows, that test processes can
get false success on this operation only to fail on later call to
something like mkdir/mknod/bind with a given path in arguments.
'get_cwd_check_perm' is a wrapper around 'get_current_dir_name'. It also
checks for permissions on the given filepath and logs the error. This
directs the developer towards the right investigation path or even
eliminates the need for investigation completely.
Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Here is a fast path when two consequent vma-s share the same file.
But one of these vma-s can map a file with MAP_SHARED, but another one
can map it with MAP_PRIVATE and we need to take this into account.
Any shared memroy mapping can be opened via /proc/self/maps_files/.
Such file descriptors look like memfd file descriptors, so
they can be dumped by the same way.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The config.h detection scripts should use the provided CFLAGS/LDFLAGS
as it tries to link libnl, libnet, and others.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
We should ignore (not parse) images that has non-crtool format,
that images has no magic number (RAW_IMAGE_MAGIC equals 0).
nftables images has format compatible with `nft -f /proc/self/fd/0`
input format.
Reported-by: Mr Jenkins
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
The file only includes other headers (which may be not needed).
If we aim for one-include-for-compel, we could instead paste all
subheaders into "compel.h".
Rather, I think it's worth to migrate to more fine-grained compel
headers than follow the strategy 'one header to rule them all'.
Further, the header creates problems for cross-compilation: it's
included in files, those are used by host-compel. Which rightfully
confuses compiler/linker as host's definitions for fpu regs/other
platform details get drained into host's compel.
Signed-off-by: Dmitry Safonov <dima@arista.com>
The plan is to remove "compel.h". That file only includes other headers
(which may be not needed). If we aim for one-include-for-compel, we
could instead paste all subheaders into "compel.h".
Rather, I think it's worth to migrate to more fine-grained compel
headers than follow the strategy 'one header to rule them all'.
Further, the header creates problems for cross-compilation: it's
included in files, those are used by host-compel. Which rightfully
confuses compiler/linker as host's definitions for fpu regs/other
platform details get drained into host's compel.
As a first step - stop including "compel.h" in criu.
Signed-off-by: Dmitry Safonov <dima@arista.com>
To really open symlink file and not the regular file below it, one needs
to do open with O_PATH|O_NOFOLLOW flags. Looks like systemd started to
open /etc/localtime symlink this way sometimes, and before that nobody
actually used this and thus we never supported this in CRIU.
Error (criu/files-ext.c:96): Can't dump file 11 of that type [120777]
(unknown /etc/localtime)
Looks like it is quiet easy to support, as c/r of symlink file is almost
the same as c/r of regular one. We need to only make fstatat not
following links in check_path_remap.
Also we need to take into account support of ghost symlinks.
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
Co-developed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
On these test without the patch ("fown: Don't fail on dumping files opened
wit O_PATH") we trigger these errors:
Error (criu/pie/parasite.c:340): fcntl(4, F_GETOWN_EX) -> -9
Error (criu/files.c:403): Can't get owner signum on 18: Bad file descriptor
Error (criu/files-reg.c:1887): Can't restore file pos: Bad file descriptor
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
O_PATH opened files are special: they have empty
file operations in kernel space, so there not that
much we can do with them, even setting position is
not allowed. Same applies to a signal number for
owner settings.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Co-developed-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Alexander Mikhalitsyn (Virtuozzo) <alexander@mihalicyn.com>
python 2.7 doesn't call the read system call if it's read file to the
end once. The next seek allows to workaround this problem.
inhfd/memfd.py hangs due to this issue.
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Right now, criu uses a dumped fd to dump content of a memfd "file".
Here are two reasons why we should not do this:
* a state of a dumped fd doesn't have to be changed, but now criu calls
lseek on it. This can be workarounded by using pread.
* a dumped descriptor can be write-only.
Reported-by: Mr Jenkins
Cc: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The runc test cases are (sometimes) mounting a cgroup inside of the
container. For these tests to succeed, let CRIU know that cgroup2 exists
and how to restore such a mount.
This does not fix any specific cgroup2 settings, it just enables CRIU to
mount cgroup2 in the restored container.
Signed-off-by: Adrian Reber <areber@redhat.com>
More preparations for cgroupv2 freezer. Factor our the freezer state
opening and writing to have one location where to handle v1 and v2
differences.
Signed-off-by: Adrian Reber <areber@redhat.com>
The cgroupv2 freezer does not return the same strings as v1. Instead of
THAWED and FROZEN v2 returns 0 and 1 (strings). This prepares the seize
code to use 0 and 1 everywhere and THAWED and FROZEN only for v1
specific code paths.
Signed-off-by: Adrian Reber <areber@redhat.com>
This option was introduced with:
e2c38245c6
v2: (comment from Pavel Tikhomirov) --enable-fs does not fit with
--external dev[]:, see try_resolve_ext_mount, external dev mounts
only determined for FSTYPE__UNSUPPORTED.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
In the recent kernels the userfaultfd support for FORK events is limited to
CAP_SYS_PTRACE. That causes the followong error when the ioctl(UFFDIO_API)
is executed from non-privilieged userns:
Error (criu/uffd.c:273): uffd: Failed to get uffd API: Operation not permitted
Wrapping the call to ioctl(UFFDIO_API) in userns_call() resolves the issue.
Fixes: #964
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
gcc8 in Fedora Rawhide has a new useful warning:
> criu/img-remote.c: In function 'push_snapshot_id':
> criu/img-remote.c:1099:2: error: 'strncpy' specified bound 4096 equals destination size [-Werror=stringop-truncation]
> 1099 | strncpy(rn.snapshot_id, snapshot_id, PATH_MAX);
> | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From man 3 strncpy:
> Warning: If there is no null byte among the first n bytes of src,
> the string placed in dest will not be null-terminated.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Testing for all the memfd features, namely support for CR of:
* the same fd shared by multiple processes
* the same file shared by multiple processes
* the memfd content
* file flags and fd flags
* mmaps, MAP_SHARED and MAP_PRIVATE
* seals, excluding F_SEAL_FUTURE_WRITE because this feature only exists
in recent kernels (5.1 and up)
* inherited fd
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
File pairs naturally block on read() until the write() happen (or the
writer is closed). This is not the case for regular files, so we
take extra precaution for these.
Also cleaned-up an extra my_file.close()
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
See "man fcntl" for more information about seals.
memfd are the only files that can be sealed, currently. For this
reason, we dump the seal values in the MEMFD_INODE image.
Restoring seals must be done carefully as the seal F_SEAL_FUTURE_WRITE
prevents future write access. This means that any memory mapping with
write access must be restored before restoring the seals.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
* During checkpoint, we add a vma flags: VMA_AREA_MEMFD to denote memfd
regions.
* Even though memfd is backed by the shmem device, we use the file
semantics of memfd (via /proc/map_files/<vma>) which we already have
support for.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Upon file restore, inherited_fd() is called to check for a user-defined
inerit-fd override. Note that the MEMFD_INODE image is read at each
invocation (memfd name is not cached).
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
See "man memfd_create" for more information of what memfd is.
This adds support for memfd open files, that are not not memory mapped.
* We add a new kind of file: MEMFD.
* We add two image types MEMFD_FILE, and MEMFD_INODE.
MEMFD_FILE contains usual file information (e.g., position).
MEMFD_INODE contains the memfd name, and a shmid identifier
referring to the content.
* We reuse the shmem facilities for dumping memfd content as it
would be easier to support incremental checkpoints in the future.
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Podman changed the output of 'podman ps'. For the test only running
containers are interesting. Adding the filter '-f status=running' only
returns running containers as previously.
Signed-off-by: Adrian Reber <areber@redhat.com>
Apparently, C/R is broken when CONFIG_VDSO is not set.
Probably, I've broken it while adding arm vdso support.
Or maybe some commits after.
Repair it by adding checks into vdso_init_dump(), vdso_init_restore().
Also, don't try handling vDSO in restorer if it wasn't present in
parent. And prevent summing VDSO_BAD_SIZE to {vdso,vvar}_rt_size.
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
In the current version, the offsets of remapping vvar and vdso regions
are mixed up.
If vdso is before vvar, vvar has to be mapped with the vdso_size offset.
if vvar is before vdso, vdso has to be mapped with the vvar_size offset.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On gcc-10 (and gcc-9 -fno-common) build fails as:
```
ld: criu/arch/x86/crtools.o:criu/include/cr_options.h:159:
multiple definition of `rpc_cfg_file'; criu/arch/x86/cpu.o:criu/include/cr_options.h:159: first defined here
make[2]: *** [scripts/nmk/scripts/build.mk:164: criu/arch/x86/crtools.built-in.o] Error 1
```
gcc-10 will change the default from -fcommon to fno-common:
https://gcc.gnu.org/PR85678.
The error also happens if CFLAGS=-fno-common passed explicitly.
Reported-by: Toralf Förster
Bug: https://bugs.gentoo.org/707942
Signed-off-by: Sergei Trofimovich <slyfox@gentoo.org>
Commit 0493724c8e added support for using asciidoctor
(instead of asciidoc + xmlto) to generate man pages.
For some reason, asciidoctor does not deal well with some
complex formatting that we use for options such as --external,
leading to literal ’ and ' appearing in the man page instead
of italic formatting. For example:
> --inherit-fd fd[’N']:’resource'
(here both N and resource should be in italic).
Asciidoctor documentation (asciidoctor --help syntax) tells:
> == Text Formatting
>
> .Constrained (applied at word boundaries)
> *strong importance* (aka bold)
> _stress emphasis_ (aka italic)
> `monospaced` (aka typewriter text)
> "`double`" and '`single`' typographic quotes
> +passthrough text+ (substitutions disabled)
> `+literal text+` (monospaced with substitutions disabled)
>
> .Unconstrained (applied anywhere)
> **C**reate+**R**ead+**U**pdate+**D**elete
> fan__freakin__tastic
> ``mono``culture
so I had to carefully replace *bold* with **bold** and
'italic' with __italic__ to make it all work.
Tested with both terminal and postscript output, with both
asciidoctor and asciidoc+xmlto.
TODO: figure out how to fix examples (literal multi-line text),
since asciidoctor does not display it in monospaced font (this
is only true for postscript/pdf output so low priority).
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
1. Add a/the articles where I see them missing
2. s/Forbid/disable/
3. s/crit/crit(1)/ as we're referring to a man page
4. Simplify some descriptions
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
In case asciidoc is installed and xmlto is not, make returns an error
but there's no diagnostics shown, since "xmlto: command not found"
goes to /dev/null.
Remove the redirect.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This patch fixes the problem with SSE (xmm) registers corruption on amd64
architecture. The problem was that gcc generates parasite blob that uses
xmm registers, but we don't preserve this registers in CRIU when injecting
parasite. Also, gcc, even with -nostdlib option uses builtin memcpy,
memset functions that optimized for amd64 and involves SSE registers.
It seems, that optimal solution is to use -ffreestanding gcc option
to compile parasite. This option implies -fno-builtin and also it designed
for OS kernels compilation/another code that suited to work on non-hosted
environments and could prevent future sumilar bugs.
To check that you amd64 CRIU build affected by this problem you could simply
objdump -dS criu/pie/parasite.o | grep xmm
Output should be empty.
Reported-by: Diyu Zhou <zhoudiyupku at gmail.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
This fixes the validation errors from Travis:
Build config validation
root: deprecated key sudo (The key `sudo` has no effect anymore.)
root: missing os, using the default linux
root: key matrix is an alias for jobs, using jobs
Signed-off-by: Adrian Reber <areber@redhat.com>
This is the last architecture specific change to make CRIU use clone3()
with set_tid if available. Just as on all other architectures this adds
a clone3() based assembler wrapper to be used in the restorer code.
Tested on Fedora 31 with the same 5.5.0-rc6 kernel as on the other
architectures.
Signed-off-by: Adrian Reber <areber@redhat.com>
clone3() explicitly blocks setting an exit_signal if CLONE_PARENT is
specified. With clone() it also did not work, but there was no error
message. The exit signal from the thread group leader is taken.
Signed-off-by: Adrian Reber <areber@redhat.com>
Just like on all other supported architectures gcc complains about the
stack pointer register being part of the clobber list. This removes the
stack pointer from the clobber list.
Signed-off-by: Adrian Reber <areber@redhat.com>
This adds the parasite clone3() with set_tid wrapper for s390x.
In contrast to the x86_64 implementation the thread start address and
arguments are not put on the thread stack but passed via r4 and r5. As
those registers are caller-saved they still contain the correct value
(thread start address and arguments) after returning from the syscall.
Tested on 5.5.0-rc6.
Signed-off-by: Adrian Reber <areber@redhat.com>
Just like on all other supported architectures gcc complains about the
stack pointer register being part of the clobber list:
error: listing the stack pointer register ‘15’ in a clobber list is deprecated [-Werror=deprecated]
This removes the stack pointer from the clobber list.
'zdtm.py run -a' still runs without any errors after this change.
Signed-off-by: Adrian Reber <areber@redhat.com>
With the in Linux Kernel 5.4 introduced clone3() with set_tid it is no
longer necessary to write to to /proc/../ns_last_pid to influence the
next PID number. clone3() can directly select a PID for the newly
created process/thread.
After checking for the availability of clone3() with set_tid and adding
the assembler wrapper for clone3() in previous patches, this extends
criu/pie/restorer.c and criu/clone-noasan.c to use the newly added
assembler clone3() wrapper to create processes with a certain PID.
This is a RFC and WIP, but I wanted to share it and run it through CI
for feedback. As the CI will probably not use a 5.4 based kernel it
should just keep on working as before.
Signed-off-by: Adrian Reber <areber@redhat.com>
To create a new process/thread with a certain PID based on clone3() a
new assembler wrapper is necessary as there is not glibc wrapper (yet).
Signed-off-by: Adrian Reber <areber@redhat.com>
Linux kernel 5.4 extends clone3() with set_tid to allow processes to
specify the PID of a newly created process. This introduces detection
of the clone3() syscall and if set_tid is supported.
This first implementation is X86_64 only.
Signed-off-by: Adrian Reber <areber@redhat.com>
We are running each podman test loop 50 times. This takes more than 20
minutes in Travis. Reduce both test loops to only run 20 times.
Signed-off-by: Adrian Reber <areber@redhat.com>
To ensure consistency of runtime environment processes within a
container need to see same start time values over suspend/resume
cycles. We introduce new field to the core image structure to
store start time of a dumped process. Later same value would be
restored to a newly created task. In future the feature is likely
to be pulled here, so we reserve field id in protobuf descriptor.
Signed-off-by: Valeriy Vdovin <valeriy.vdovin@virtuozzo.com>
Compiling 'criu-dev' on Fedora 31 gives two errors about wrong clobber
lists:
compel/include/uapi/compel/asm/sigframe.h:47:9: error: listing the stack pointer register ‘1’ in a clobber list is deprecated [-Werror=deprecated]
criu/arch/ppc64/include/asm/restore.h:14:2: error: listing the stack pointer register ‘1’ in a clobber list is deprecated [-Werror=deprecated]
There was also a bug report from Debian that CRIU does not build because
of this.
Each of these errors comes with the following note:
note: the value of the stack pointer after an ‘asm’ statement must be the same as it was before the statement
As far as I understand it this should not be a problem in this cases as
the code never returns anyway.
Running zdtm very seldom fails during 'zdtm/static/cgroup_ifpriomap'
with a double free or corruption. This happens not very often and I
cannot verify if it happens without this patch. As CRIU does not build
without the patch.
Signed-off-by: Adrian Reber <areber@redhat.com>
Now that Python 2 has officially reached its end of life also switch the
Alpine based test to Python 3.
Signed-off-by: Adrian Reber <areber@redhat.com>
The kernel artificially adds the O_CLOEXEC flag when reading from the
/proc/fdinfo/fd interface if FD_CLOEXEC is set on the file descriptor
used to access the file.
This commit removes the O_CLOEXEC flag in our file flags.
To restore the proper FD_CLOEXEC value in each of the file descriptors,
CRIU uses fcntl(F_GETFD) to retrieve the FD_CLOEXEC status, and restore
it later with fcntl(F_SETFD). This is necessary because multiple file
descriptors may point to the same open file.
After Centos-8 nft used instead of iptables. But we had never supported nft rules in
CRIU, and after c/r all rules are flushed.
Co-developed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
Signed-off-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Include warnings that the kernel uses during compilation:
-Wstrict-prototypes: enforces full declaration of functions.
Previously, when declaring extern void func(), one can call func(123)
and have no compilation error. This is dangerous. The correct declaration
is extern void func(void).
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
[Generated a commit message from the pull request]
Signed-off-by: Dmitry Safonov <dima@arista.com>
Include warnings that the kernel uses during compilation:
-Wdeclaration-after-statement: enforces having variables declared at the top of scopes
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
[Generated a commit message from the pull request]
Signed-off-by: Dmitry Safonov <dima@arista.com>
It seems like Ubuntu introduced a overlayfs change which breaks CRIU:
https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1857257
This disables overlayfs (unfortunately) in most tests by switching to
devicemapper or vfs.
Upstream kernels do not seem to have this problem.
This also adds the 'docker-test' for xenial which still has a working
overlayfs from CRIU's point of view.
Also adjust Podman Ubuntu package location
Podman Ubuntu packages are now available via OBS and no longer via PPA.
Signed-off-by: Adrian Reber <areber@redhat.com>
TCP keepalive packets can be used to determine if a connection
is still valid. When the SO_KEEPALIVE option is set, TCP packets
are periodically sent to keep the connection alive.
This patch implements checkpoint/restore support for SO_KEEPALIVE,
TCP_KEEPIDLE, TCP_KEEPINTVL and TCP_KEEPCNT options.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Make xfeatures_mask check explicit. We were relying on our guess about
hardware "backward compatibility" and used ">" check here for a long
time. But it looks better to explicitly check that all xfeature bits
available on the source are also available on the destination.
For xsave_size we need to have smaller size on destination than on
source, because xsave operation on small allocated buffer may corrupt
the nearby data. So split up comments about xfeatures_mask and
xsave_size, as having single comment for quiet a different cases is less
understandable.
v2: improve comments, remove extra else-ifs, remove extra typecast
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Test checks that if the /proc/sys/net/unix/max_dgram_qlen value has
been changed in process net namespace, then it is saved after c/r.
Signed-off-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
The /proc/sys/net/unix/max_dgram_qlen is a per-net variable and
we already noticed that systemd inside a container may change its value
(for example it sets it to 512 by now instead of kernel's default
value 10), thus we need keep it inside image and restore then.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Alexander Mikhalitsyn <alexander@mihalicyn.com>
Signed-off-by: Alexander Mikhalitsyn <alexander.mikhalitsyn@virtuozzo.com>
When we do clone threads in a later stage of restore procedure
it may race with helpers which do call clone_noasan by self.
Thus we need to walk over each clone_noasan call and figure
out if calling it without last_pid lock is safe.
- open_mountpoint: called by fusectl_dump, dump_empty_fs,
binfmt_misc_dump, tmpfs_dump -- they all are processing
dump stage, thus safe
- call_helper_process: try_remount_writable -- called from
various places in reg-files.c, in particular open_reg_by_id
called in parallel with other threads, needs a lock
remount_readonly_mounts -- called from sigreturn_restore,
so in parallel, needs a lock
- call_in_child_process: prepare_net_namespaces -- called
from prepare_namespace which runs before we start forking,
no need for lock
Thus call_helper_process should use lock_last_pid and
unlock_last_pid helpers and wait for subprocess to finish.
Same time put a warning text into clone_noasan comment
so next time we need to use it we would recall the pitfalls.
v2:
- fix unitialized ret variable
v3:
- use exit_code instead of ret
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
We've seen ppoll interrupted with signal in VZ7 CT migration tests, that
is because in the beggining of CR_STATE_RESTORE_SIGCHLD zombies and
helpers die, and that can trigger SIGCHILDs sent to their parents.
Adding additional debug (printing "Task..." for zombies and helpers) in
sigchld_handler I see:
(15.644339) pie: 1: Task 10718 exited, status= 0
(15.644349) pie: 1: Cleaning inotify events from 29
(15.644359) pie: 1: Cleaning inotify events from 19
(15.644367) pie: 1: Cleaning inotify events from 10
And previousely we had:
(05.718449) pie: 104: Cleaning inotify events from 5
(05.718835) pie: 330: Cleaning inotify events from 3
(05.719046) pie: 1: Cleaning inotify events from 23
(05.719164) pie: 80: Cleaning inotify events from 7
(05.719185) pie: 1: Error (criu/pie/restorer.c:1287): Failed to poll from inotify fd: -4
(05.719202) pie: 95: Cleaning inotify events from 6
(05.719269) pie: 1: Error (criu/pie/restorer.c:1890): Restorer fail 1
So reordering cleanup and wait should fix it.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Fixes the following compile-error:
> CC socket-tcp-fin-wait1.o
> socket-tcp-fin-wait1.c:144:26: error: adding 'int' to a string does not append to the string [-Werror,-Wstring-plus-int]
> if (write(fd, TEST_MSG + 2, sizeof(TEST_MSG) - 2) != sizeof(TEST_MSG) - 2) {
> ~~~~~~~~~^~~
> socket-tcp-fin-wait1.c:144:26: note: use array indexing to silence this warning
> if (write(fd, TEST_MSG + 2, sizeof(TEST_MSG) - 2) != sizeof(TEST_MSG) - 2) {
> ^
> & [ ]
> 1 error generated.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The original/old guide probably doesn't work anymore:
- the patch isn't accessible;
- criu now depends on more libraries not only protobuf
Still, keep it as it might be helpful for someone.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Helps to cross-compile zdtm tests in case somebody needs it.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The very same hack to build aarch32 zdtm tests on armv8 Travis-CI
as in the commit dfa0a1edcb ("Makefile hack for travis
aarch64/armv8l")
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Instead of doing additional `uname -m` - use provided $(SUBARCH) to detect
what architecture flavour the build should produce the result for.
Fixes two things:
- zdtm make now correctly supplies $(USERCFLAGS)
- subtly fixes cross compilation by providing a way to specify $(SUBARCH)
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
It's always equal ARCH and not very useful (so nothing actually uses it).
Time for a change: SUBARCH now is meaningful and gives a way to detect
what kind of ARCH flavor build is dealing with.
Also, for cross-compiling sake don't set SUBARCH if the user supplied it.
(and don't call useless uname during cross compilation)
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
SRCARCH is always equal ARCH. There are no rules when to use one or
another and architectures may forget to set one of them up.
No need for a second variable meaning the same and confusing people.
Remove it completely.
Self-correction [after some debug]: SRCARCH was different in one place:
zdtm Makefile by some unintentional mistake:
> ifeq ($(ARCH),arm64)
> ARCH ?= aarch64
> SRCARCH ?= aarch64
> endif
That meant to be "ARCH := aarch64" because "?=" would never work inside
that ifeq. Fix up this part of mess too.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Update zdtm tests to verify that CRIU does not require the --root
path to be accessible to the unprivileged user being restored when
restoring user namespace.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Replacing the if->continue pattern with if->elif->else
reduces the number of lines while preserving the logic.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
When restoring a container with user namespace, CRIU fails to create
a temporary directory for proc. The is because the unprivileged user
that has been just restored does not have permissions to access the
working directory used by CRIU.
Resolves#828
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
When restoring a runc container with enabled user namespace CRIU fails
to mount the specified root directory because the path is under
/run/runc which is inaccessible to unprivileged users.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Kernels 5.4 and higher will restrict availability of UFFD_EVENT_FORK only
for users with SYS_CAP_PTRACE. This prevents running --lazy-pages tests
with 'uns' flavor.
Disable 'uns' for lazy pages testing in travis for newer kernels.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Before this change CRIU would checkpoint all controllers, even the ones
not specified in --cgroup-dump-controller. That becomes a problem if
there's a cgroup controller on the checkpointing machine that doesn't
exist on the restoring machine even if CRIU is instructed not to dump
that controller. After that change everything works as expected.
Signed-off-by: Michał Cłapiński <mclapinski@google.com>
All those compel functions can fail by various reasons.
It may be status of the system, interruption by user or anything else.
It's really desired to handle as many PIE related errors as possible
otherwise it's hard to analyze statuses of parasite/restorer
and the C/R process.
At least warning for logs should be produced or even C/R stopped.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Currently if anything fails after network has been unlocked tasks aren't
killed. Which doesn't work anyway: any stage sets `ret` and nothing
later gets called. Which means the tasks aren't resumed properly.
Furthermore, functions like catch_tasks() and compel_stop_on_syscall()
return failure on the first error.
Let's do the cleanup even when the network is unlocked.
If we want to keep the mess and ignore failures - a cli option should be
introduced for that (and existing code should be reworked with decisions
what is critical and what can be ignored).
Move "Restore finished successfully" message accordingly where
everything is evidently good.
While at here, any late failure will result not only in cleanup but in
criu returning error code.
Which in result makes tests to fail in such case:
> ======================= Run zdtm/static/inotify04 in ns ========================
> Start test
> ./inotify04 --pidfile=inotify04.pid --outfile=inotify04.out --dirname=inotify04.test
> Run criu dump
> =[log]=> dump/zdtm/static/inotify04/84/1/dump.log
> ------------------------ grep Error ------------------------
> (00.119763) fsnotify: openable (inode match) as zdtm/static/inotify04.test/inotify-testfile
> (00.119766) fsnotify: Dumping /zdtm/static/inotify04.test/inotify-testfile as path for handle
> (00.119769) fsnotify: id 0x00000b flags 0x000800
> (00.119787) 88 fdinfo 5: pos: 0 flags: 4000/0
> (00.119796) Warn (criu/fsnotify.c:336): fsnotify: The 0x00000c inotify events will be dropped
> ------------------------ ERROR OVER ------------------------
> Run criu restore
> =[log]=> dump/zdtm/static/inotify04/84/1/restore.log
> ------------------------ grep Error ------------------------
> (00.391582) 123 was stopped
> (00.391667) 106 was trapped
> (00.391674) 106 (native) is going to execute the syscall 11, required is 11
> (00.391697) 106 was stopped
> (00.391720) Error (compel/src/lib/infect.c:1439): Task 123 is in unexpected state: b7f
> (00.391736) Error (compel/src/lib/infect.c:1447): Task stopped with 11: Segmentation fault
> ------------------------ ERROR OVER ------------------------
> 5: Old maps lost: set([])
> 5: New maps appeared: set([u'10000-1a000 rwxp', u'1a000-24000 rw-p'])
> ############### Test zdtm/static/inotify04 FAIL at maps compare ################
> Send the 9 signal to 106
> Wait for zdtm/static/inotify04(106) to die for 0.100000
> ======================= Test zdtm/static/inotify04 PASS ========================
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Unknown state means that the task in the end may be not in wanted state.
Return err code.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Maybe expected, hopefully never happens - let's warn in any case.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Too late to stop restore: it's already printed that restore was
successful. Oh, well warn aloud about infection.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Probably, not the worst that could happen, but still unexpected.
Preparing the ground to make compel_cure*() functions __must_check.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On daemon stop or threads dump failures it's still desired to remove
parasite from the remote (if possible). Try best and keep hopeing.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
As a preparation for __must_check on compel_syscall(), check it on
close() too - maybe not as useful as with other syscalls, but why not.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Also, don't use the magic -2 => return errno on failure.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
>From man ptrace:
> On error, all requests return -1, and errno is set appropriately.
> Since the value returned by a successful PTRACE_PEEK* request may be
> -1, the caller must clear errno before the call, and then check
> it afterward to determine whether or not an error occurred.
FWIW: if ptrace_peek_area() is called with (errno != 0) it may
false-fail if the data is (-1).
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Now that Travis also supports ppc64le and s390x we can remove all qemu
based docker emulation from our test setup. This now runs ppc64le and
s390x tests on real hardware (LXD containers).
Signed-off-by: Adrian Reber <areber@redhat.com>
This switches all arm related tests (32bit and 64bit) to the aarch64
systems Travis provides. For arm32 we are running in a armv7hf container
on aarch64 with 'setarch linux32'.
The main changes are that docker on Travis aarch64 cannot use
'--privileged' as Travis is using unprivileged LXD containers to setup
the testing environment.
Signed-off-by: Adrian Reber <areber@redhat.com>
For CRIU's compile only tests for armv7hf on Travis we are using
'setarch linux32' which returns armv8l on Travis aarch64.
This adds a path in the Makefile to treat armv8l just as armv7hf during
compile. This enables us to run armv7hf compile tests on Travis aarch64
hardware. Much faster. Maybe not entirely correct, but probably good
enough for compile testing in an armv7hf container.
Signed-off-by: Adrian Reber <areber@redhat.com>
Travis uses unprivileged containers for aarch64 in LXD. Docker with
'--privileged' fails in such situation. This changes the travis setup
to only start docker with '--privileged' if running on x86_64.
Signed-off-by: Adrian Reber <areber@redhat.com>
In my previous commit I copied a line with a return into the main script
body. bash can only return from functions. This changes return to exit.
Signed-off-by: Adrian Reber <areber@redhat.com>
Add mnt_subtree_next DFS-next search to remove recursion.
v5: add these patch, remove recursion from sorting helpers
v6: rip out butifull yet unused step-part of nfs-next algorithm
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Build each mntns mount tree alone just after reading mounts for it from
image. These additional step before merging everything to a single mount
tree allows us to have pointers to each mntns root mount at hand, also
it allows us to remove extra complication from mnt_build_tree.
Teach collect_mnt_from_image return a tail pointer, so we can merge
lists together later after building each tree.
Add separate merge_mount_trees helper to create joint mount tree for all
mntns'es and simplify mnt_build_ids_tree.
I don't see any place where we use mntinfo_tree on restore, so save the
real root of mntns mounts tree in it, instead of root_yard_mp, will need
it in next patches for checking restore of these trees.
v2: prepend children to the root_yard in merge_mount_trees so that the
order in merged tree persists
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Images for mount and net namespaces are empty if ns does not belong to
us, thus we don't need to collect on restore.
By adding these checks we will eliminate suspicious messages in logs
about lack of images:
./test/zdtm.py run -k always -f h -t zdtm/static/env00
env00/54/2/restore.log:(00.000332) No mountpoints-5.img image
env00/54/2/restore.log:(00.000342) No netns-2.img image
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The path:
restore_root_task
prepare_namespace_before_tasks
mntns_maybe_create_roots
is always called before the path below:
retore_root_task
fork_with_pid
restore_task_with_children
prepare_namespace
prepare_mnt_ns
populate_mnt_ns
So (!!mnt_roots) == (root_ns_mask & CLONE_NEWNS) in populate_mnt_ns, but
in prepare_mnt_ns we've already checked that it is true, so there is no
need in these check - remove it.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
It seems pretty stable and hasn't add many false-positives during last
months. While can reveal some issues for compatible C/R code.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Update test to support both iptables and nft to create conntrack rules.
Signed-off-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
With the newly introduced aarch64 at Travis it is possible for the CRIU
test-cases to switch to aarch64.
Travis uses unprivileged LXD containers on aarch64 which blocks many of
the kernel interfaces CRIU needs. So for now this only tests building
CRIU natively on aarch64 instead of using the Docker+QEMU combination.
All tests based on Docker are not working on aarch64 is there currently
seems to be a problem with Docker on aarch64. Maybe because of the
nesting of Docker in LXD.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signal masks propagate through execve, so we need to clear them before
invoking the action scripts as it may want to handle SIGCHLD, or SIGSEGV.
Signed-off-by: Nicolas Viennot <nicolas.viennot@twosigma.com>
I don't see many issues with early-log, so we probably don't
need the warning when it was used. Note that after
commit 74731d9 ("zdtm: make grep_errors also grep warnings")
also warnings are grepped by zdtm.py (and I believe that was
an improvement) which prints some bothering lines:
> =[log]=> dump/zdtm/static/inotify00/38/1/dump.log
> ------------------------ grep Error ------------------------
> (00.000000) Will allow link remaps on FS
> (00.000034) Warn (criu/log.c:203): The early log isn't empty
> ------------------------ ERROR OVER ------------------------
Instead of decreasing loglevel of the message, improve it by
reporting a real issue.
Cc: Adrian Reber <adrian@lisas.de>
Cc: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cc: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
PATH is pointing to incorrect location for `criu` executable
causing libcriu tests to fail when running in travis.
Also added statements to display log file contents on failure
to help in debugging.
Signed-off-by: Ashutosh Mehra <asmehra1@in.ibm.com>
libcriu tests are currently broken. This patch fixes couple of
issues to allow the building and running libcriu tests.
1. lib/c/criu.h got updated to include version.h which is present
at "criu/include", but the command to compile libcriu tests is not
specifying "criu/include" in the path to be searched for header
files. This resulted in compilation error.
This can be fixed by adding "-I ../../../../../criu/criu/include"
however it causes more problems as "criu/include/fcntl.h" would now
hide system defined fcntl.h
Solution is to use "-iquote ../../../../../criu/criu/include"
which applies only to the quote form of include directive.
2. Secondly, libcriu.so major version got updated to 2 but
libcriu/run.sh still assumes verion 1. Instead of just updating the
version in libcriu/run.sh to 2, this patch updates the libcriu/Makefile
to use "CRIU_SO_VERSION_MAJOR" so that future changes to major version
of libcriu won't cause same problem again.
Signed-off-by: Ashutosh Mehra <asmehra1@in.ibm.com>
RPC messages are have fairly small size and using space on the stack
might be a better option. This change follows the pattern used with
do_pb_read_one() and pb_write_one().
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The support for per-pid images with locks has been dropped with
commit d040219 ("locks: Drop support for per-pid images with locks")
and CR_FD_FILE_LOCKS_PID is not used.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
When performing pre-dump we continuously increase the page-pipe size to
fit the max amount memory pages in the pipe's buffer. However, we never
actually set the pipe's buffer size to max. By doing so, we can reduce
the number of pipe-s necessary for pre-dump and improve the performance
as shown in the example below.
For example, let's consider the following process:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void main(void)
{
int i = 0;
void *cache = calloc(1, 1024 * 1024 * 1024);
while(1) {
printf("%d\n", i++);
sleep(1);
}
}
stats-dump before this change:
frozen_time: 123538
memdump_time: 95344
memwrite_time: 11980078
pages_scanned: 262721
pages_written: 262169
page_pipes: 513
page_pipe_bufs: 519
stats-dump after this change:
frozen_time: 83287
memdump_time: 54587
memwrite_time: 12547466
pages_scanned: 262721
pages_written: 262169
page_pipes: 257
page_pipe_bufs: 263
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The lock status string may be empty. This can happen when the owner of
the lock is invisible from our PID namespace. This unfortunate behavior
is fixed in kernels v4.19 and up (see commit 1cf8e5de40)
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Conflict register for file "sk-opts.proto": READ is already defined in
file "rpc.proto". Please fix the conflict by adding package name on the
proto file, or use different name for the duplication. Note: enum
values appear as siblings of the enum type instead of children of it.
https://github.com/checkpoint-restore/criu/issues/815
Signed-off-by: Andrei Vagin <avagin@gmail.com>
atomic_sub isn't defined for all platforms.
Reported-by: Mr Jenkins
Cc: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
lib/c/criu.c:343:30: error: implicit conversion from enumeration type
'enum criu_pre_dump_mode' to different enumeration type 'CriuPreDumpMode'
(aka 'enum _CriuPreDumpMode') [-Werror,-Wenum-conversion
opts->rpc->pre_dump_mode = mode;
~ ^~~~
Signed-off-by: Andrei Vagin <avagin@gmail.com>
refactoring time macros as per read mode
pre-dump design.
Signed-off-by: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Pre-dump using the process_vm_readv syscall.
During frozen state, only iovecs will be
generated and draining of memory happens
after the task is unfrozen. Pre-dumping of
shared memory remains unmodified.
Signed-off-by: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
adding cnt_sub function (complement of cnt_add).
cnt_sub is utilized to decrement stats counter
according to skipped page count during "read"
mode pre-dump.
Signed-off-by: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
"read" mode pre-dump may fail even after
adding PROT_READ flag. Adding PROT_READ
works when dumping statically. See added
comment for details.
Signed-off-by: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Skip iov-generation for regions not having
PROT_READ, since process_vm_readv syscall
can't process them during "read" pre-dump.
Handle random order of "read" & "splice"
pre-dumps.
Signed-off-by: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Two modes of pre-dump algorithm:
1) splicing memory by parasite
--pre-dump-mode=splice (default)
2) using process_vm_readv syscall
--pre-dump-mode=read
Signed-off-by: Abhishek Dubey <dubeyabhishek777@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
1) Instead of tampering with the nr argument, do_full_int80() returns
the value of the system call. It also avoids copying all registers back
into the syscall_args32 argument after the syscall.
2) Additionally, the registers r12-r15 were added in the list of
clobbers as kernels older than v4.4 do not preserve these.
3) Further, GCC uses a 128-byte red-zone as defined in the x86_64 ABI
optimizing away the correct position of the %rsp register in
leaf-functions. We now avoid tampering with the red-zone, fixing a
SIGSEGV when running mmap_bug_test() in debug mode (DEBUG=1).
Signed-off-by: Nicolas Viennot <Nicolas.Viennot@twosigma.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Right now, it is created from the pre-dump hook, but
if the --snap option is set, the test fails:
$ python test/zdtm.py run -t zdtm/static/cgroup_yard -f h --snap --iter 3
...
Running zdtm/static/cgroup_yard.hook(--pre-dump)
Traceback (most recent call last):
File zdtm/static/cgroup_yard.hook, line 14, in <module>
os.mkdir(yard)
OSError: [Errno 17] File exists: 'external_yard'
Cc: Michał Cłapiński <mclapinski@google.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Right now it is cleaned up from a post-restore hook,
but zdtm.py can be executed with the norst option:
$ zdtm.py run -t zdtm/static/cgroup_yard --norst
...
OSError: [Errno 17] File exists: 'external_yard'
Cc: Michał Cłapiński <mclapinski@google.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Prior log initialisation CRIU preserves all (early) log messages in a
buffer. In case of error the content of the content of this buffer
needs to be printed out (flushed).
Suggested-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Before the 5.2 kernel, only fpu_state->fpu_state_64.xsave has to be
64-byte aligned. But staring with the 5.2 kernel, the same is required
for pu_state->fpu_state_ia32.xsave.
The behavior was changed in:
c2ff9e9a3d9d ("x86/fpu: Merge the two code paths in __fpu__restore_sig()")
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Instead of creating cgroup yard in CRIU, now we can create it externally
and pass it to CRIU. Useful if somebody doesn't want to grant
CAP_SYS_ADMIN to CRIU.
Signed-off-by: Michał Cłapiński <mclapinski@google.com>
`pushq` sign-extends the value. Which is a bummer as the label's address
may be higher that 2Gb, which means that the sign-bit will be set.
As it long-jumps with ia32 selector, %r11 can be scratched.
Use %r11 register as a temporary to push the 32-bit address.
Complements: a9a760278c ("arch/x86: push correct eip on the stack
before lretq")
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Reported-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Right now we use pushq, but it pushes sign-extended value, so if the
parasite code is placed higher that 2Gb, we will see something like
this:
0xf7efd5b0: pushq $0x23
0xf7efd5b2: pushq $0xfffffffff7efd5b9
=> 0xf7efd5b7: lretq
Actually we want to push 0xf7efd5b9 instead of 0xfffffffff7efd5b9.
Fixes: #398
Cc: Dmitry Safonov <dima@arista.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Acked-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The function clear_ghost_files() has been removed in commit
b11eeea "restore: auto-unlink for ghost files (v2)".
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Here we have some bugfixes, huuuge *.py patch for coding style
and nice set of new features like 32bit for ARM, TLS for page
server and new mode for CGroups.
Signed-off-by: Pavel Emelyanov <xemul@openvz.org>
Reduce code duplication by taking setup_swrk() function into a separate
module that can be reused in multiple places.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
When Python 2 is not installed we assume that /usr/bin/python refers to
version 3 of Python and the executable /usr/bin/python2 does not exist.
This commit also resolves a compatibility issue with Popen where in
Py2 file descriptors will be inherited by the child process and in
Py3 they will be closed by default.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
As discussed on the mailing list, current .py files formatting does not
conform to the world standard, so we should better reformat it. For this
the yapf tool is used. The command I used was
yapf -i $(find -name *.py)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
After adding the test for fake inotify events cleanup on restore, we've
detected that we also have the same problem on dump/predump, criu
touches files that are watched and generates fake events:
[root@snorch criu]# test/zdtm.py run -t zdtm/static/inotify04 --norst -k always
=== Run 1/1 ================ zdtm/static/inotify04
======================== Run zdtm/static/inotify04 in h ========================
Start test
./inotify04 --pidfile=inotify04.pid --outfile=inotify04.out --dirname=inotify04.test
Run criu dump
=[log]=> dump/zdtm/static/inotify04/36/1/dump.log
------------------------ grep Error ------------------------
(00.004050) fsnotify: openable (inode match) as home/snorch/devel/criu/test/zdtm/static/inotify04.test/inotify-testfile
(00.004052) fsnotify: Dumping /home/snorch/devel/criu/test/zdtm/static/inotify04.test/inotify-testfile as path for handle
(00.004055) fsnotify: id 0x000007 flags 0x000800
(00.004071) 36 fdinfo 5: pos: 0 flags: 4000/0
(00.004080) Warn (criu/fsnotify.c:336): fsnotify: The 0x000008 inotify events will be dropped
------------------------ ERROR OVER ------------------------
Send the 15 signal to 36
Wait for zdtm/static/inotify04(36) to die for 0.100000
############### Test zdtm/static/inotify04 FAIL at result check ################
Test output: ================================
18:20:10.558: 36: Event 0x20
18:20:10.558: 36: Event 0x10
18:20:10.558: 36: Event 0x20
18:20:10.558: 36: Event 0x10
18:20:10.558: 36: Event 0x20
18:20:10.558: 36: Event 0x10
18:20:10.558: 36: Event 0x20
18:20:10.558: 36: Event 0x10
18:20:10.558: 36: Read 8 events
18:20:10.558: 36: FAIL: inotify04.c:105: Found 8 unexpected inotify events (errno = 11 (Resource temporarily unavailable))
<<< ================================
##################################### FAIL #####################################
To suppress fails in jenkins make the inotify04 test 'reqrst'. Still
need to cleanup (or do not create) these events on dump/predump.
This adds the same tests currently running for docker also for podman.
In addition this also tests podman --export/--import (migration)
support.
Signed-off-by: Adrian Reber <areber@redhat.com>
If vvar is absent vdso_before_vvar is initialized by "false".
Which means that the check that supposed to track vdso/vvar pair went
into wrong brackets. In result it broke CRIU on kernels that don't have
vvar mapping.
Simpilfy the code by moving the check for VVAR_BAD_SIZE outside of
conditional for vdso_before_vvar.
Reported-by: Cyrill Gorcunov <gorcunov@gmail.com>
Fixes: 0918c76676 ("vdso/restorer: Always track vdso/vvar positions in
vdso_maps_rt")
Signed-off-by: Dmitry Safonov <dima@arista.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Tested-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This is needed to workaround the problem with "ip route save":
(00.113153) Running ip route save
Error: ipv4: FIB table does not exist.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Just create two inotify watches on a testfile, and do nothing except
c/r, it is expected that there is no events in queue after these.
before "inotify: cleanup auxiliary events from queue":
[root@snorch criu]# ./test/zdtm.py run -t zdtm/static/inotify04
=== Run 1/1 ================ zdtm/static/inotify04
======================== Run zdtm/static/inotify04 in h ========================
DEP inotify04.d
CC inotify04.o
LINK inotify04
Start test
./inotify04 --pidfile=inotify04.pid --outfile=inotify04.out --dirname=inotify04.test
Run criu dump
Run criu restore
Send the 15 signal to 60
Wait for zdtm/static/inotify04(60) to die for 0.100000
=============== Test zdtm/static/inotify04 FAIL at result check ================
Test output: ================================
18:37:14.279: 60: Event 0x10
18:37:14.280: 60: Event 0x20
18:37:14.280: 60: Event 0x10
18:37:14.280: 60: Read 3 events
18:37:14.280: 60: FAIL: inotify04.c:105: Found 3 unexpected inotify events (errno = 11 (Resource temporarily unavailable))
<<< ================================
v2: make two inotifies on the same file
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
zdtm: inotify04 add another inotify on the same file
I've mentioned the problem that after c/r each inotify receives one or
more unexpected events.
This happens because our algorithm mixes setting up an inotify watch on
the file with opening and closing it.
We mix inotify creation and watched file open/close because we need to
create the inotify watch on the file from another mntns (generally). And
we do a trick opening the file so that it can be referenced in current
mntns by /proc/<pid>/fd/<id> path.
Moreover if we have several inotifies on the same file, than queue gets
even more events than just one which happens in a simple case.
note: For now we don't have a way to c/r events in queue but we need to
at least leave the queue clean from events generated by our own.
These, still, looks harder to rewrite wd creation without this proc-fd
trick than to remove unexpected events from queues.
So just cleanup these events for each fdt-restorer process, for each of
its inotify fds _after_ restore stage (at CR_STATE_RESTORE_SIGCHLD).
These is a closest place where for an _alive_ process we know that all
prepare_fds() are done by all processes. These means we need to do the
cleanup in PIE code, so need to add sys_ppoll definitions for PIE and
divide process in two phases: first collect and transfer fds, second do
real cleanup.
note: We still do prepare_fds() for zombies. But zombies have no fds in
/proc/pid/fd so we will collect no in collect_fds() and therefore we
have no in prepare_fds(), thus there is no need to cleanup inotifies for
zombies.
v2: adopt to multiple unexpected events
v3: do not cleanup from fdt-receivers, done from fdt-restorer
v4: do without additional fds restore stage
v5: replace sys_poll with sys_ppoll and fix minor nits
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
use ppoll always and remove poll
Omit calling raw syscalls and use vdso for the purpose of logging.
That will eliminate as much as one-syscall-per-PIE-message.
Getting time without switching to kernel will speed up C/R,
keeping logs as informative as they were.
Fixes: #346
I haven't enabled vdso timings for ia32 applications as it needs more
changes and complexity.. Maybe later.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We need to differ compatible (ia32) vdso maps from x86_64.
That dictates ABI on vdso code.
According to that, the decision to (not) use gettimeofday() from vdso in
64-bit restorer.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
For simplicity, make them always valid in restorer.
rt->vdso_start will be used to calculate gettimeofday() address.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
vdso will be used in restorer for timings in logs - try to keep it
during restore process.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Provide a way to set gettimeofday() function for an infected task.
CRIU's parasite & restorer are very voluble as more logs are better
than lesser in terms of bug investigations.
In all modern kernels there is a way to get time without entering
kernel: vdso. So, add a way to reduce the cost of logging without making
it less valuable.
[I'm not particularly fond of std_log_set_gettimeofday() name, so
if someone can come with a better naming - I'm up for a change]
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Doesn't change uapi, but makes it a bit more friendly and documented
which loglevel means what for foreign user.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The following error is falsely reported by flake8:
lib/py/images/pb2dict.py:266:24: F821 undefined name 'basestring'
This error occurs because `basestring` is not available in Python 3,
however the if condition on the line above ensures that this error
will not occur at run time.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
In the Fedora tests we install python3-pip only to install flake8.
This is not necessary as there is a Fedora package for flake8.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
More and more python2 packages are being removed from future Fedora
releases. This removes python2 packages explicitly listed in CRIU's
Dockerfiles, which all are not required for the current level of
testing.
Signed-off-by: Adrian Reber <areber@redhat.com>
To be able to run the test containers in scripts/build with podman this
puts the name of the container runtime into $CONTAINER_RUNTIME.
Now it can be overridden with
make fedora-rawhide CONTAINER_RUNTIME=podman
Signed-off-by: Adrian Reber <areber@redhat.com>
Including the version information of CRIU in criu.h is required by
projects that use libcriu to preserve backward compatibility.
Closes#738
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Since we use _i as a counter in macro declaration
we should use it as a reference. This macro simply
happen to work now because of being called with
variable i declarated in the caller code.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
To get error message in log if no memory available.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
To shrink code a bit.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
When logs are massive it is convenient for grepping.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
No need to spam on every pmc_init call.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
- make names more descriptive
- add comments
- use union for nr_priv_pages and rst_priv_size since
former priv_size has been used with different meaning:
number of pages during checkpoint time and size in bytes
on restore moment
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
To eliminate side effects, in particular setting nr_aios
is already missing here.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Integer value is too short.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We allocate with xzalloc, no need for additional zero assignemtns.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In case if we may use previous pipe the pipe_off
get set directly so no need for redundat unconditional
assignment.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
1. Basic check if property is migrated
2. Check that property is restored for existing children
3. Check that child subreaper does not affect reparenting
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Michał Cłapiński <mclapinski@google.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
1. Checkpoint it via parasite.
2. Restore it after forking.
Signed-off-by: Michał Cłapiński <mclapinski@google.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
The `libprotobuf-c0-dev` virtual package is no longer available
in Debian Buster, but is provided by `libprotobuf-c-dev`, which
is available.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
In zdtm.py, the page size is hardcoded as 4096, but on ppc64le, is is equal
to 64K and all test fail with errors like this:
ERROR: bad page counts, stats = 13 real = 208(0)
Signed-off-by: Andrei Vagin <avagin@gmail.com>
It is inspired by the discussion about inotify fix:
https://github.com/checkpoint-restore/criu/pull/728#issuecomment-506929427
From one point of view, warnings might be important to understand why we
detect some visible change in the environment after c/r-ing the process,
and if this change is expected or not. So we should add "Warn" messages
to the output.
From over point, these warnings if they are expected, can spoil our
final logs with a lot of unnecessary details, so add changes in previous
patches to silence the most noisy of these warnings.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We want to grep warnings from zdtm tests to travis final logs.
And I see a lot of these:
Warn (criu/image.c:137): Failed to open parent directory
If there is no parent images directory then there is no previous dump
and no pid-reuse problem with pagemaps possible, so it is fine to have
no parent inventory image at the same time which is used here to fix the
problem. These always hapens on the first iteration of iterative dump.
So don't warn here.
While on it also fix error message in detect_pid_reuse.
v2: add detect_pid_reuse part
v3: improve comments
We want to grep warnings from zdtm tests to travis final logs.
And I see a lot of these:
(00.250989) Warn (criu/pagemap.c:90): Missing 7f84103e3000 in parent pagemap
(00.250999) p 0x7f84103f5000 [1]
We do a lookup of an intersecting pagemap entry with a memory region we
want to dedup, it is expected that sometimes we don't have some subrange
in pagemap entries. So these should not be a warning, make it debug
message.
While on it change the message to save us from been confused with other
"Missing..." error messages, and change abstract "parent image" message
to the IDs of pages image in all messages in dedup_one_iovec().
v2: print image ids
criu-3.12/criu/files-reg.c:774: leaked_storage: Variable "img" going out
of scope leaks the storage it points to.
criu-3.12/criu/files-reg.c:788: leaked_storage: Variable "img" going out
of scope leaks the storage it points to.
criu-3.12/criu/files-reg.c:797: leaked_storage: Variable "img" going out
of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/util.c:879:9: warning: Null pointer passed as an argument
to a 'nonnull' parameter
criu-3.12/criu/util.c:1171:3: warning: Value stored to 'ret' is never
read
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/seize.c:648: leaked_storage: Variable "threads" going out
of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/sk-inet.c:575: identical_branches: The same code is
executed when the condition "pb_write_one(img_from_set(glob_imgset,
CR_FD_FILES), &fe, PB_FILE)" is true or false, because the code in the
if-then branch and after the if statement is identical. Should the if
statement be removed?
Signed-off-by: Adrian Reber <areber@redhat.com>
Instead of using tty_mutex value in atomic context
(which is wrong, since it is not atomic) better move
tty_mutex allocation into cr_restore_tasks where our
all initializers live. Otherwise weird race effect
might be observed.
Reported-by: Deng Guangxing <dengguangxing@huawei.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Segmentation fault was raised while trying to restore a process with
tty. Coredump file says this is caused by uninitialized tty_mutex:
(gdb) where
#0 0x00000000004d7270 in atomic_add_return (i=1, v=0x0) at
include/common/asm/atomic.h:34
#1 0x00000000004d7398 in mutex_lock (m=0x0) at
include/common/lock.h:151
#2 0x00000000004d840c in __pty_open_ptmx_index (index=3, flags=2,
cb=0x4dce50 <open_pty>, arg=0x11, path=0x5562e0 "ptmx") at
criu/tty.c:603
#3 0x00000000004dced8 in pty_create_ptmx_index (dfd=17, index=3,
flags=2) at criu/tty.c:2384
since init_tty_mutex() is reentrantable, just calling it before
mutex_lock()
Signed-off-by: Deng Guangxing <dengguangxing@huawei.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
By default, CRIU will verify the certificate of a server (with
gnutls_certificate_verify_peers3()) by providing the value specified
with "--address" as a hostname.
As part of the verification process, this value will be compared
against the common name (CN) included in the TLS certificate of the
server. If the CN doesn't match the TLS handshake will be terminated
and CRIU will exit with an error.
Although, this is an important feature that is used to mitigate MITM
attacks, a user might need to disable such hostname verification for
a particular use case or testing purposes.
For instance, this option is needed when the common name included in
the certificate corresponds to the server's domain name and an IP
address is being used to establish connection.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
This commit adds Transport Layer Security (TLS) support for remote
page-server connections.
The following command-line options are introduced with this commit:
--tls-cacert FILE Trust certificates signed only by this CA
--tls-cacrl FILE CA certificate revocation list
--tls-cert FILE TLS certificate
--tls-key FILE TLS private key
--tls Use TLS to secure remote connections
The default PKI locations are:
CA certificate /etc/pki/CA/cacert.pem
CA revocation list /etc/pki/CA/cacrl.pem
Client/server certificate /etc/pki/criu/cert.pem
Client/server private key /etc/pki/criu/private/key.pem
The files cacert.pem and cacrl.pem are optional. If they are not
present, and not explicitly specified with a command-line option,
CRIU will use only the system's trusted CAs to verify the remote
peer's identity. This implies that if a CA certificate is specified
using "--tls-cacert" only this CA will be used for verification.
If CA certificate (cacert.pem) is not present, certificate revocation
list (cacrl.pem) will be ignored.
Both (client and server) sides require a private key and certificate.
When the "--tls" option is specified, a TLS handshake (key exchange)
will be performed immediately after the remote TCP connection has been
accepted.
X.509 certificates can be generated as follows:
-------------------------%<-------------------------
# Generate CA key and certificate
echo -ne "ca\ncert_signing_key" > temp
certtool --generate-privkey > cakey.pem
certtool --generate-self-signed \
--template temp \
--load-privkey cakey.pem \
--outfile cacert.pem
# Generate server key and certificate
echo -ne "cn=$HOSTNAME\nencryption_key\nsigning_key" > temp
certtool --generate-privkey > key.pem
certtool --generate-certificate \
--template temp \
--load-privkey key.pem \
--load-ca-certificate cacert.pem \
--load-ca-privkey cakey.pem \
--outfile cert.pem
rm temp
mkdir -p /etc/pki/CA
mkdir -p /etc/pki/criu/private
mv cacert.pem /etc/pki/CA/
mv cert.pem /etc/pki/criu/
mv key.pem /etc/pki/criu/private
-------------------------%<-------------------------
Usage Example:
Page-server:
[src]# criu page-server -D <PATH> --port <PORT> --tls
[dst]# criu dump --page-server --address <SRC> --port <PORT> \
-t <PID> -D <PATH> --tls
Lazy migration:
[src]# criu dump --lazy-pages --port <PORT> -t <PID> -D <PATH> --tls
[dst]# criu lazy-pages --page-server --address <SRC> --port <PORT> \
-D <PATH> --tls
[dst]# criu restore -D <PATH> --lazy-pages
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
There are two notable open-source libraries that provide TLS
implementation - OpenSSL and GnuTLS. The license of OpenSSL
is incompatible with CRIU's license, and threfore GnuTLS is
the recommended choice.
GnuTLS offers an API to access secure communication protocols. These
protocols provide privacy over insecure lines, and are designed to
prevent eavesdropping, tampering or message forgery.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
- make sure the alloc_openable is not failed with
memory error, so that we should not lookup via
irmap
- irmap lookup should provide us a copy of the path
instead of reference to irmap entry
https://github.com/checkpoint-restore/criu/issues/698
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Vigorously remove the config ifdef.
The config option *never* had any excuse to exist:
- for x86 we were grand
- for ppc64/arm64 patches to support mremap() on vdso were long ago
accepted, but regardless - it's not possible to disable CONFIG_VDSO for
those platforms in kernel
- for s390 - patches were mainstreamed not that long ago, but it's not
possible to disable the kernel config
- for arm32 it's possible to disable the kernel config, but kernel
returns to userspace historically through sigpage, not vdso.
That's the only platform that criu disallows to have CONFIG_VDSO=y in
kernel, but that's just meaningles. A kernel patch for sigpage mremap()
has gone into v4.13: commit 280e87e98c09 ("ARM: 8683/1: ARM32: Support
mremap() for sigpage/vDSO").
So, removing the config was long-lived item on my TODO list that bligted
arm32 users and made changes to vdso more complex by all "needed"
iffdeferry. Get rid of it with fire.
Fixes: #446
Signed-off-by: Dmitry Safonov <dima@arista.com>
There is a little difference between ccflags-y and CFLAGS, except the
local/global visibility: nmk adds $(CFLAGS) to nmk-asflags and assembles
using them, but without ccflags-y.
The other possible way would be adding asflags-y with CFLAGS_PIE, but
I'm not convinced - let's update CFLAGS for the time being.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Rather than chain[chain] != STN_UNDEF.
Seems like, on !ARM32 vdso there are more symbols and less chance to hit
this "feature".
Fixes parsing of __vdso_clock_gettime symbol on v5.1 arm kernel.
Signed-off-by: Dmitry Safonov <dima@arista.com>
The patch "util-vdso: Check chain for STN_UNDEF" fixed an issue about
not discovering present symbols on vdso. While it's a good and a proper
fix, as the result __kernel_vsyscall started being patched.
Which in result broke zdtm trampoline test on ia32.
So, let's omit patching vsyscall while #512 issue is not fixed.
We might actually refrain patching it for long time as it doesn't access
vvar, so there is little sense in doing patching.
Signed-off-by: Dmitry Safonov <dima@arista.com>
After patching code - we need to flush CPU cache, it's done with
__builtin___clear_cache(). As we don't link to libgcc, provide a helper
that wraps ARM-specific syscall.
Fixes:
LINK criu/pie/restorer.built-in.o
ld: ./criu/arch/arm/vdso-pie.o: in function `insert_trampoline':
/root/criu/criu/arch/arm/vdso-pie.c:32: undefined reference to `__clear_cache'
Signed-off-by: Dmitry Safonov <dima@arista.com>
We're building PIEs in arm format rather than in thumb.
Copy helpers from libgcc, provide a proper define and
link them into blobs.
Also substitute tabs by spaces, how it should have been
in pie/Makefile - tabs are for recipes.
Fixes:
LINK criu/pie/parasite.built-in.o
criu/pie/pie.lib.a(util-vdso.o): In function `elf_hash':
/criu/criu/pie/util-vdso.c:61: undefined reference to `__aeabi_uidivmod'
/criu/scripts/nmk/scripts/build.mk:209: recipe for target 'criu/pie/parasite.built-in.o' failed
Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com>
criu/pie/parasite-vdso.c: In function 'remap_rt_vdso':
criu/pie/parasite-vdso.c:144:17: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
if (sys_munmap((void *)vma_vdso->start, vma_entry_len(vma_vdso))) {
^
criu/pie/parasite-vdso.c:154:17: error: cast to pointer from integer of different size [-Werror=int-to-pointer-cast]
if (sys_munmap((void *)vma_vvar->start, vma_entry_len(vma_vvar))) {
^
cc1: all warnings being treated as errors
Signed-off-by: Dmitry Safonov <dima@arista.com>
During restore any VMA that's a subject to ASLR should be moved at the
same address as was on a checkpoint. Previously, ports to non-x86
architectures had problems with VDSO mremap(). On those platforms kernel
needs "landing" for return to userspace in some cases.
Usually, vdso provides this landing and finishes restoring of registers.
That's `int80_landing_pad` on ia32. On arm64/arm32 it's sigtrap for
SA_RESTORER - to proceed after signal processing.
That's why kernel needs to track the position of landing.
On modern kernels for platform we support it's already done - however,
for older kernels some patches needs to be backported for C/R.
Provide the checks for mremap() of special VMAs: that CRIU has suitable
kernel to work on and if we'll have some new platforms - that kernel
tracks the position of landing.
Signed-off-by: Dmitry Safonov <dima@arista.com>
In the __main__ module, __builtins__ is the built-in module builtins.
In any other module, __builtins__ is an alias for the dictionary of
the builtins module itself. [1]
Thus, hasattr(__builtins__, "basestring") would only work in __main__
module. Since pb2dict is part of pycriu and is intended to be called
by modules other than __main__, we can assume that __builtins__ would
always be a dictionary (not a module).
In Python 2, basestring is a superclass for str and unicode. [2]
However, the assignment statement creates a variable basestring in the
local scope of the function is_string() which, in Python 2, causes a
failure with UnboundLocalError. In order to mitigate this issue the
local variable name has been changed to string_types.
Fixes#708
[1] https://docs.python.org/2/reference/executionmodel.html#builtins-and-restricted-execution
[2] https://docs.python.org/2/library/functions.html#basestring
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Since gcc version 9.1 was added the restriction that the clobber list
of an inline assembly should not contain the stack pointer register.
https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=9d1cdb749a1
In commit 901f5d4 have been fixed most of the build failures related to
this gcc restriction. In this patch is resolved a build error that
occurs only on aarch64.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Right now we use fcntl(F_GETFD) to check whether a target descriptor
is used and then we call dup2(). Actually, we can do this for one system
call.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Dumping shmem segments causing stats "pages written" counter to mismatch
the real pages* sizes. This is due to ipcns' dumping happens in another
process and the relevant shmem dumping counters remain in its address space.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
After dump command -- verify that the amount of bytes counted in
stats-dump matches the real sizes of pages-*.img files.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Shmem pages are written in the same set of images as regular
pages are, but stats for those are not collected. Fix this, but
keep the counts separate to have more info.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Since commit b5dff62e we skipped updating dump stats for pages
that overflowed the page-pipe and thus got flushed in "chunk"
mode.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The final release of asciidoc was on Sep 29, 2017 and the development
is continued under asciidoctor.
With commit 0493724 (Documentation: Allow to use asciidoctor for
formatting man pages) was added support for this tool by introducing
USE_ASCIIDOCTOR.
However, using asciidoctor by default might be a better option. With
this change CRIU will use asciidoctor if installed. Otherwise, it will
fallback to asciidoc.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
From the python-six module is used only six.string_types in the
is_string() function. An alternative solution is to use
basestring with additional if statement for Python 3 compatibility.
This change avoids the dependency on the six module.
However, this module is required by junit_xml and it is not listed
as a dependency in the CentOS 7 package python2-junit_xml.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
criu-3.12/criu/image.c:103: leaked_storage: Variable "img" going out of
scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/util.c:505: var_deref_model: Passing null pointer "dir"
to "dirfd", which dereferences it. (The dereference is assumed on the
basis of the 'nonnull' parameter attribute.)
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/sk-unix.c:1893: leaked_handle: Handle variable "sk" going
out of scope leaks the handle.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/proc_parse.c:2280: leaked_storage: Variable "dir" going
out of scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
criu-3.12/criu/pagemap.c:694: var_deref_model: Passing "pr" to
"free_pagemaps", which dereferences null "pr->pmes"
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/mem.c:597:3: warning: Value stored to 'ret' is never read
criu-3.12/criu/mem.c:632: leaked_storage: Variable "img" going out of
scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/lib/c/criu.c:255: leaked_storage: Variable "rpc" going out of
scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
This fixes a coverity buffer overflow warning:
criu-3.12/criu/log.c:344: overrun-local: Overrunning array of 1024 bytes
at byte offset 1031 by dereferencing pointer "early_log_buffer +
early_log_buf_off + log_size". [Note: The source code implementation of
the function has been overridden by a builtin model.]
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/files-reg.c:1574: dereference: Dereferencing "rmi", which
is known to be "NULL".
criu-3.12/criu/files-reg.c:1582: dereference: Dereferencing "tmi", which
is known to be "NULL".
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/files.c:1250: leaked_storage: Variable "dir" going out of
scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/cr-service.c:933:7: warning: Access to field 'keep_open'
results in a dereference of a null pointer (loaded from variable 'msg')
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/cr-service.c:1305: fixed_size_dest: You might overrun the
108-character fixed-size string "server_addr.sun_path" by copying
"opts.addr" without checking the length.
Signed-off-by: Adrian Reber <areber@redhat.com>
criu-3.12/criu/autofs.c:114: leaked_storage: Variable "path" going out
of scope leaks the storage it points to.
criu-3.12/criu/autofs.c:254: leaked_storage: Variable "opts" going out
of scope leaks the storage it points to.
criu-3.12/criu/autofs.c:719: leaked_storage: Variable "path" going out
of scope leaks the storage it points to.
criu-3.12/criu/autofs.c:980: leaked_storage: Variable "img" going out of
scope leaks the storage it points to.
Signed-off-by: Adrian Reber <areber@redhat.com>
for Intel Apollo Lake SOC, its cpuinfo and fpu features:
cpu: x86_family 6 x86_vendor_id GenuineIntel x86_model_id Intel(R) Celeron(R) CPU J3455 @ 1.50GHz
cpu: fpu: xfeatures_mask 0x11 xsave_size 1088 xsave_size_max 1088 xsaves_size 704
cpu: fpu: x87 floating point registers xstate_offsets 0 / 0 xstate_sizes 160 / 160
this CPU doesn't have AVX registers, YMM feature.
when CRIU runs on this CPU, it will report dump error:
Dumping GP/FPU registers for 4888
Error (criu/arch/x86/crtools.c:362): x86: Corruption in XFEATURE_YMM area (expected 64 but 0 obtained)
Error (criu/cr-dump.c:1278): Can't infect (pid: 4888) with parasite
that's because x86/crtools.c will still valid YMM xsave frame, thus fail to dump.
bypass unsupported feature, to make CRIU runs this kinds of CPUs.
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We don't need patching vdso neither in parasite nor in criu.
Move it to restorer-only objects.
Note that we need filling symtables everywhere (kdat/parasite/restorer),
this change doesn't move util-vdso.o which has vdso_fill_symtable().
[those files ask for a proper rename, but it's not directly related to
the change, so yet TODO]
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Do the cleanup that was long pending by XXX :)
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
It's needed for PIEs, but not for the library.
It comes earlier than commit 61e6c01d09, but I don't see the point.
Regardles, I'm a bit afraid to break s390, hopefully testing covers the
platform.
This and the next one "make: Move CR_NOGLIBC into CFLAGS_PIE" should be
reverted/dropped from criu-dev if they turn to be breaking something.
Cc: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
As pie.lib.a linked also to PIEs - we need to use missing flags as
-nostdlib and -fomit-frame-pointer.
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
There ain't even such path in sources.
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
As far as I know, difference between CFLAGS and ccflags-y in kernel is
that CFLAGS are global and exported and ccflags-y are per-Makefile.
So, exporting ccflags-y should be omitted.
While at it, remove COMPEL_UAPI_INCLUDES - they're added to CFLAGS
straight away and exported to sub-makes, so no-one need to include them
twice.
Also, remove from sub-Makefiles -iquote(s) for includes those are already
added in criu/Makefile
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
__ASSEMBLY__ is used to guard C-related code in headers from
asm-compatible defines. We actually want every .S file to be assembled
with -D__ASSEMBLY__ not to burst with C in asm file.
Move __ASSEMBLY__ from all local asflags to top Makefile's AFLAGS.
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
I don't want to see CFLAGS redefined per-architecture in PIE makefiles
in couple of places. Clean it up.
The only expected per-arch ifdeffery should be object files.
Also add a big comment about -marm vs -mthumb[2]
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
And drop a stale comment that doesn't clearify anything.
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The commit 5432a964dc ("lazy-pages: don't mark current stack page as
lazy") tried to make the pages surrounding the stack pointers non-lazy.
Unfortunately, it used a wrong mask for the detection.
Fix it.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
When check_options() exits with an error (return value != 0) the
logging is not yet initialised, and therefore the error messages
are not printed out.
Since this affects only command-line usage, and only when
check_options() reports an error, flush the early log
messages to STDERR.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
In daemon mode the standard file descriptors 0, 1 and 2 will be closed
and ps-socket should not be one of them.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
When running lazy-pages in daemon mode, file descriptor 3 is reused
after fork to 'protect' the opened UNIX socket. However, fd 3 happens
to correspond to the opened image directory. Thus, when this file
descriptor is overwritten CRIU fails with the following error:
$ criu lazy-pages -D <PATH> --page-server \
--address <ADDR> --port <PORT> -d
...
(06.835596) Error (criu/image.c:470): Unable to open pagemap-1.img: Not a directory
(06.835855) Error (criu/uffd.c:773): uffd: 1-7: Failed to open pagemap
The need for keep_fd is really only necessary if the file descriptor we
would like to 'protect' is 0, 1 or 2. Assuming that the standard file
descriptors STDIN, STDOUT and STDERR are open this hack is unnecessary.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Inet sockets may have broadcasting capability enabled. The SO_BROADCAST
option is used to enable this feature. It is a Boolean flag option,
which is defined, fetched, and set with the int data type. During
checkpoint, CRIU should detect the state of this flag, and during
restore, it should be set appropriately.
Fixes#673
Reported-by: @dubukuangye
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The built-in bool() function returns a boolean value by converting the
input using standard truth testing procedure.
https://docs.python.org/3/library/functions.html#bool
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Since commit 6c572bee8f ("cgroup: Set "soft" mode by default") it
become impossible to set ignore mode at all. Provide a user option to do
that.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
ia32 thread-bomb test failed when compel refused to seize the test,
trying to mmap() in remote process and getting ENOMEM.
It turns to be true - remote process thread-bomb was filled with 8Mb
mappings created by pthread_create() (the default stack size).
So, that 1024 * 8Mb is a bit too much to place in 4Gb.
Fix the test on 32-bit platforms by using much smaller stack.
Also check the return value of pthread_create().
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Not a major bummer.
On the other side, it's also becomes less important as it seems that
distribution switches from LEGACY_VSYSCALL_EMULATE to
LEGACY_VSYSCALL_NONE (by security reasons).
Might be not worth fixing at all in the end.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Add some comments to state things those might be not obvious.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
sizeof(fd) is the size of the pointer. Make sure the entire array is set
by using the number of elements times the size of the elements.
Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Remove a redundant if-statement, since the same condition is already
checked in the outer if-statement.
Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
If read() fails we can not use the return value as index. Move the use
of it to after the error check to avoid this.
Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In a function with return type bool, returning a non-zero value is
interpreted as returning true. In the error paths we want to return
false to indicate failure. Change -1 to false to fix this.
Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
sizeof(sizeof(x)) is the size of size_t. Instead use the size of the
array to ensure the entire array is zeroed.
Signed-off-by: Rikard Falkeborn <rikard.falkeborn@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
stack for clone is too small, child process will get
wild pointer, and segfault.
Error (criu/cr-restore.c:1418): 6082 killed by signal 11: Segmentation fault
Error (criu/cr-restore.c:2303): Restoring FAILED.
enlarge stack size to 1024, then no segfault.
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
If socket has been connected and shutted down, it may get
disconnected then leaving shutdown mode set inside (which
we pull into image). On restore we should not fail when
calling shutdown over -- the kernel has a hack to inform
listeners even on closed sockets. From userspace perspective
to reuse such socket one have to connect it back, so should
be safe.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
to enable Hygon Dhyana, which can reuse most AMD CPU support codes.
Signed-off-by: hygonsoc <hygonsoc@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
There are a few places where spaces have been used instead of tabs for
indentation. This patch converts the spaces to tabs for consistency
with the rest of the code base.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
A bit nasty, but does the job to run ofd tests on glibc < v2.28.
Other way would be to update glibc on Travis-CI ia32 tests, but
I thought someone might want to run the tests outside Travis-CI.
Fixes: #745
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
As discusses on the musl mailing list [1] when libc api is used to
create a POSIX thread, and this thread is killed by seccomp, this
breaks a fundamental assumption the C runtime relies on, causing
any libc call (i.e. pthread_join) after the kill to have undefined
behaviour.
In order to work around the issue we could use SECCOMP_RET_ERRNO
instead of SECCOMP_RET_KILL. This filter will set a magic value
to user space as errno without executing the system call.
[1] https://www.openwall.com/lists/musl/2019/06/26/7
Rresolves #725
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Reading out the xattr 'security.selinux' of checkpointed sockets with
fscanf() works (at least in theory) without checking the result of
fscanf(). There are, however, multiple CI failures when ignoring the
return value of fscanf().
This adds ferror() to check if the stream has an actual error or if '-1'
just mean EOF.
Handle all errors of fscanf() // Andrei
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This adds two more SELinux test to verfy that checkpointing and
restoring SELinux socket labels works correctly, if the process uses
setsockcreatecon() or if the process leaves the default context for
newly created sockets.
Signed-off-by: Adrian Reber <areber@redhat.com>
Restoring a SELinux process also requires to correctly label sockets.
During checkpointing fgetxattr() is used to retrieve the
"security.selinux" xattr and during restore setsockcreatecon() is used
before a socket is created.
Previous commits are already restoring the sockcreate SELinux setting if
set by the process.
Signed-off-by: Adrian Reber <areber@redhat.com>
The file /proc/PID/attr/sockcreate is used by SELinux to label newly
created sockets with the label available at sockcreate.
If it is NULL, the default label of the process will be used.
This reads out that file during checkpoint and restores the value during
restore.
This value is irrelevant for existing sockets as they might have been
created with another context. This is only to make sure that newly
created sockets have the correct context.
Signed-off-by: Adrian Reber <areber@redhat.com>
Suddenly it's a feature-reach release. We have support for Android build
and several tempting C/R things -- raw sockets, selinux labels and ro
ghost files.
And a couple of fixes, of course.
FOO ?= bar
is equivalent to
ifeq ($(origin FOO), undefined)
FOO = bar
endif
However, when CC is not set its value is 'default' rather than
'undefined'.
>From [1]:
'undefined': if variable was never defined.
'default': if variable has a default definition, as is usual with CC
and so on. See Variables Used by Implicit Rules. Note that if you have
redefined a default variable, the origin function will return the
origin of the later definition.
[1] https://www.gnu.org/software/make/manual/make.html
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
libcriu.so used to have the SONAME
$ readelf -d lib/c/libcriu.so | grep SONAME
0x000000000000000e (SONAME) Library soname: [libcriu.so.1]
The recent changes to libcriu (removed and added functions, changes from
`char *`-args to `const char *`) are breaking ABI and API. This requires
a new SONAME of 2. This patch changes the SONAME to 2:
$ readelf -d lib/c/libcriu.so | grep SONAME
0x000000000000000e (SONAME) Library soname: [libcriu.so.2]
Signed-off-by: Adrian Reber <areber@redhat.com>
For swrk, service, dump, restore we need to to raise
nr_file limit to be able to process containers with
huge number of files opened.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
It has nothing to do with utils but
rather a separate service engine.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
It has a different alignment - rework ugly macro RT_SIGFRAME_UC_SIGMASK
into helpers.
Fixes: #666
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Travis CI with Xenial has 4.15 kernel these days - all support for ia32
C/R should be inplace. Finally :)
Putting it into "allow_failures" to let it soak a bit.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
due to Android NDK's clang is x86_64-linux-android28-clang --sysroot ${SYSROOT_PATH}
and it's ld is x86_64-linux-android-ld,
it's not able to use a single pattern to discript clang and ld.
and there is a error for x86_64-linux-android-ld.
x86_64-linux-android-ld -L/home/ning/source/criu/protobuf-c/../target/lib -lprotobuf-c -r -z noexecstack -T ./compel/arch/x86/scripts/compel-pack.lds.S -o criu/pie/parasite.built-in.o criu/pie/parasite.o criu/pie/pie.lib.a ./compel/plugins/std.lib.a
./compel/compel-host hgen -f criu/pie/parasite.built-in.o -o criu/pie/parasite-blob.h
Error (compel/src/lib/handle-elf-host.c:335): Unexpected undefined symbol: `'. External symbol in PIE?
criu/pie/Makefile:49: recipe for target 'criu/pie/parasite-blob.h' failed
rebuild with host ld, can pass build.
so support override CC/LD from command line can pass build.
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
criu/log.c:356:16: error: called object type 'int' is not a function or function pointer
int __errno = errno;
^~~~~
/root/android-ndk/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/include/errno.h:43:24: note: expanded from macro 'errno'
~~~~~~~^
criu/log.c:391:2: error: called object type 'int' is not a function or function pointer
errno = __errno;
^~~~~
/root/android-ndk/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/include/errno.h:43:24: note: expanded from macro 'errno'
in Android NDK's errno.h:
42: int* __errno(void) __attribute_const__;
43: #define errno (*__errno())
so rename __errno to _errno to pass build
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
it reports:
criu/pie/util-vdso-elf32.c:255:8: error: implicit declaration of function 'ELF32_ST_TYPE' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
if (ELF_ST_TYPE(sym->st_info) != STT_FUNC &&
^
criu/include/util-vdso.h:72:21: note: expanded from macro 'ELF_ST_TYPE'
^
/opt/android-ndk/toolchains/llvm/prebuilt/linux-x86_64//sysroot/usr/include/linux/elf.h:114:26: note: expanded from macro 'ELF32_ST_TYPE'
^
criu/include/util-vdso.h:72:21: note: expanded from macro 'ELF_ST_TYPE'
add #ifndef to check whether these macro is already defined.
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
with Android P's Clang versoin: 6.0.2, and Android NDK's Clang version 8.0.2
Clang will report below error:
criu/compel/include/uapi/compel/sigframe-common.h:55:34: error: expected member name or ';' after declaration specifiers
int __unused[32 - (sizeof (k_rtsigset_t) / sizeof (int))];
~~~ ^
it takes __unused as an attribute, not a varible, chang to _unused, pass compile.
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
in Android NDK, <elf.h> doesn't has define for:
NT_X86_XSTATE
NT_PRSTATUS
so add these defines to pass compile.
NOTE: add <linux/elf.h> will have more build errors
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We want to commit --check-mounts feature to vz-criu. But to maintain
image level compatibility between ms-criu and vz-criu one shouldn't use
the same field id for different data. So add a comment that these id is
reserved.
due to Android NDK's strings.h doesn't have index function.
Declare this function in CRIU, just like povit_root.
still need to provide index function implement, for link CRIU.
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
1, do not hardcode libnl's cflags
when cross compile CRIU, libnl's header file should not point to host.
2, remove link to rt
Android NDK doesn't have library rt, and CRIU is not really need it,
so disable it to pass link
Cc: Chen Hu <hu1.chen@intel.com>
Signed-off-by: Zhang Ning <ning.a.zhang@intel.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Restoring a multi-threaded process with CRIU's SELinux support fails
because SELinux does not always support changing the process context of
a multi-threaded process.
Reading the man-page for setcon(), to change the context of a running
process, it states that changing the SELinux context of a multi-threaded
process can only work 'if the new security context is bounded by the old
security context'.
To be able to restore a process without the need to have 'the new
security context [] bounded by the old security context', this sets the
SELinux process context before creating the threads. Thus all threads
are created with the process context of the main process.
Signed-off-by: Adrian Reber <areber@redhat.com>
The flag --security-opt doesn't use the colon separator (:) anymore
to divide keys and values, instead it uses the equal symbol (=) for
consistency with other similar flags, like --storage-opt.
Deprecated in release: v1.11.0
Target for removal in release: v17.06
https://docs.docker.com/engine/deprecated/#653
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
This tests if CRIU can restore a process with the same policy as during
checkpointing.
The test selinux00 is started and if SELinux is available the test
process moves itself to another process context. To make this possible
either a new SELinux policy needs to be available containing:
2d537cabbb
Or for a short time SELinux is switched to permissive mode.
The correct SELinux setup is done by zdtm/static/selinux00.checkskip and
zdtm/static/selinux00.hook and after the test the previous SELinux
policy state is restored.
After the test case is restored the test case checks if it still has the
same SELinux process context as before. If not the test cases fails.
Signed-off-by: Adrian Reber <areber@redhat.com>
If running on a system with SELinux enabled the socket for the
communication between parasite daemon and the main CRIU process needs to
be correctly labeled.
Initially this was motivated by Podman's use case: The container is
usually running as something like '...:...:container_t:...:....' and
CRIU started from runc and Podman will run as
'...:...:container_runtime_t:...:...'. As the parasite will be running
with the same context as the container process: 'container_t'.
Allowing a container process to connect via socket to the outside
of the container ('container_runtime_t') is not desired and therefore
CRIU needs to label the socket with the context of the
container: 'container_t'.
So this first gets the context of the root container process and tells
SELinux to label the next created socket with the same label as the root
container process. For this to work it is necessary to have the correct
SELinux policies installed. For Fedora based systems this is part of the
container-selinux package.
This assumes that all processes CRIU wants to dump are labeled with the
same SELinux context. If some of the child processes have different
labels this will not work and needs additional SELinux policies. But the
whole SELinux socket labeling relies on the correct SELinux being
available.
Signed-off-by: Adrian Reber <areber@redhat.com>
There was support for SELinux process labels in CRIU but because it was
never tested or verified CRIU only supported the 'unconfined_t' process
label. This was basically no SELinux support.
For successful container checkpoint and restore on a SELinux enabled
host it is necessary that the restored container has the same process
context as before checkpointing.
This commit only removes the check if the label is 'unconfined_t' and
now stores any process label to be restored.
For 'normal' processes started from the command-line which are usually
running in the 'unconfined_t' this just works.
For the container use case this needs additional policies. The latest
container-selinux package on Fedora has the necessary policy to allow
CRIU (running as 'container_runtime_t' when used from Podman) to
transition the restored process to 'container_t'.
Restoring a process running under systemd's control (which means
'unconfined_service_t' without additional policies) will fail because
CRIU will be not allowed to change the context of the restored process.
For each additional CRIU use case on SELinux enabled systems, besides
container processes and command-line/shell processes, additional SELinux
policies are required to allow CRIU to do a 'dyntransition' (change the
Signed-off-by: Adrian Reber <areber@redhat.com>
It was never designed to run params in ansync mode,
and i always been against this change because async
here is too fragile.
p.s.:
I think this might be a reason for
https://github.com/checkpoint-restore/criu/issues/647
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Removed return value assignment statements as they are not referenced or used
anywhere after the assignment is done.
Fixes#334: Removing Unneeded Assignments
Signed-off-by: Mitul Karnik <mitulkarnik.92@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Use faccessat() in check_path_remap() to check if the file (relative
to root of mnt ns) is accessible or not.
Signed-off-by: Ashutosh Mehra <asmehra1@in.ibm.com>
binfmt_misc.c:168:23: error: ‘sprintf’ may write a terminating nul past the end of the destination [-Werror=format-overflow=]
168 | sprintf(path, "%s/%s", dirname, NAME[i]);
| ^
Signed-off-by: Adrian Reber <areber@redhat.com>
Support for printing early log messages was recently added, which makes this
comment is no longer relevant.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
In rpc.proto the interface to query the CRIU version number uses major
and minor as keywords. This creates errors when using the RPC
definitions with C++: https://github.com/checkpoint-restore/criu/issues/625
In this commit the fields are renamed from major to major_number and
from minor to minor_number.
For existing programs using the RPC protobuf definition this should be a
transparent change. Only for programs importing the latest rpc.proto it
will require code changes.
Signed-off-by: Adrian Reber <areber@redhat.com>
Combine the functionality of socket_set_non_blocking() and
socket_set_blocking() into a new function, and move it in
criu/util.c to enable reusability throughout the code base.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
When the --ps-socket option is specified the provided file descriptor
of a socket will be reused for incoming TCP connection. In such case
the --address and --port options are ignored.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The variable `len` is used only to calculate the value of `end`. We
already have the static inline function pagemap_len(), which can be
used instead.
Acked-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The server socket is marked as nonblocking, and if the client doesn't
connect, accept() will fail and set errno to EAGAIN (or EWOULDBLOCK).
Instead, use poll to wait for POLLIN event on the file descriptor.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Running crit with python2 gives following minimal help message:
$ crit/crit
usage: crit [-h] {decode,encode,info,x,show} ...
crit: error: too few arguments
Using a python3 only system crit shows the following error:
$ crit/crit
Traceback (most recent call last):
File "crit/crit", line 6, in <module>
cli.main()
File "/home/criu/crit/pycriu/cli.py", line 334, in main
opts["func"](opts)
KeyError: 'func'
Using this patch the python3 output changes to:
$ crit/crit
usage: crit [-h] {decode,encode,info,x,show} ...
crit: error: too few arguments
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
When the --ps-socket option is used with page-server, instead of
--address and --port, this message would appear as:
(00.028440) Disconnect from the page server (null):0
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
From man inet_pton(3):
inet_pton() returns 1 on success (network address was successfully
converted). 0 is returned if src does not contain a character
string representing a valid network address in the specified
address family. If af does not contain a valid address family,
-1 is returned and errno is set to EAFNOSUPPORT.
We can assume that the return value is 1 or 0 (because af is set to
AF_INET4 or AF_INET6), therefore errno will not be set.
If a user attempts to bind a server using invalid network address the
following error message will be shown:
Bad server address: Success
Which is not very clear, with this change the error message will look
like this:
Invalid server address "localhost". The address must be in IPv4 or IPv6 format.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
* "post-resume" was introduced with commit:
2ab599398d
cr-restore: "post-resume" hook introduced
This hook is called at the very end, when everything is restored and processes
were resumed.
Can be used for some actions, which require operation container, like
restarting of systemd autofs services.
* "post-setup-namespaces" was introduced with commit:
eec66f3d30
criu [PATCH] post-setup-namespaces
Introduce post-setup-namespaces action script
It needed to have possibility to run cutom script after mount
namespace is configured
* "orphan-pts-master" was introduced with commit:
6afe523d97
tty: notify about orphan tty-s via rpc
Now Docker creates a pty pair from a container devpts to use is as console.
A slave tty is set as a control tty for the init process and bind-mounted
into /dev/console. The master tty is handled externelly.
Now CRIU can handle external resources, but here we have internal resources
which are used externaly.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Suppress the false positive fail in criu-live-migration job:
https://ci.openvz.org/job/CRIU/job/criu-live-migration/job/criu-dev/1796/
[criu]# ./test/zdtm.py run -t zdtm/static/overmounted_file -f uns --lazy-migrate
=== Run 1/1 ================ zdtm/static/overmounted_file
=================== Run zdtm/static/overmounted_file in uns ====================
Start test
Test is SUID
./overmounted_file --pidfile=overmounted_file.pid --outfile=overmounted_file.out --dirname=overmounted_file.test
Run criu dump
Test zdtm/static/overmounted_file FAIL at criu dump exited with 1 ######
Send the 9 signal to 49
Wait for zdtm/static/overmounted_file(49) to die for 0.100000
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The '-R' is short for '--leave-running', which is a boolean option and
does not require an argument.
From getopt(3) man page:
optstring is a string containing the legitimate option characters. If
such a character is followed by a colon, the option requires an
argument, ...
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
This commit removes the functions criu_(local_)set_service_comm().
These functions are not neccessary, because if
set_service_address(), set_service_fd() or
set_service_binary() has been called it is already clear, which
service comm type should be used.
Furhtermore, this commit reduces the number of misuses.
E.g. if set_service_comm() was set to socket, but a binary was given
via set_service_binary().
Signed-off-by: Martin Wührer <martin.wuehrer@artech.at>
This commit checks after each strdup() call if the call was successful.
If not, the function that calls strdup() returns an error.
This requires, that the return value of several functions has to be
changed from void to int.
Signed-off-by: Martin Wührer <martin.wuehrer@artech.at>
Files from such mounts can switch on restore to different files on the
overmounting mount, as we yet don't fully control the mount on which
the file is restored.
v3: make mnt_is_overmounted boolean again
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Test creates two shared mounts, both are readonly, on each mount we have
a different ghost file. Also let these mounts have different mount
flags. That makes us both test do_new_mount hunk for delaying readonly
and do_bind_mount, as one mount will bind from another on restore.
https://jira.sw.ru/browse/PSBM-82991
v2: minor cleanup
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
We can have ghost-files on readonly mounts, for them we will need to
recreate the file on restore, and we can't do that if mount is readonly,
so the idea is to remount the mount we want to operate on to be writable,
and later after all ghost-files restored return mounts to their proper
state if needed.
There are three exceptions, where we don't remount:
a) Overmounted mounts can't be easily remounted writable, as their
mountpoints are invisible for us.
b) If the mount has readonly superblock - there can be no ghost-files on
such a mount.
c) When we are in host mntns, we should not remount mounts in it, else
if we face errors in between we'll forget to remount back.
We have 3 places where we need to add these remount:
1) create_ghost()
2) clean_one_remap()
3) rfi_remap()
For (1) and (2) we can just remount the mount writable without
remounting it back as they are called in service mntns (the one we save
in mnt_ns_fd), which will be destroyed with all it's mounts at the end.
We mark such mounts as remounted in service mntns - REMOUNTED_RW_SERVICE.
For (3) we need to remount these mounts back to readonly so we mark them
with REMOUNTED_RW and later in remount_readonly_mounts all such mounts
are re-remounted back.
For (3) we also need to enter proper mntns of tmi before remounting.
These solution v3 is better than v2 as for v2 we added additional
remount for all bind-readonly mounts, now we do remounts only for
those having ghost-files restore operations on them. These should be
quiet a rare thing, so ~3 remounts added for each suitable mount is a
relatively small price.
note: Also I thought and tried to implement the complete remove of the
step of remounting back to readonly, but it requires quiet a tricky
playing with usernsd and only removes one remount (of ~3) for already a
rare case so I don't thing it worth the effort.
v2: minor commit message cleanup and remove warn
v4: don't delay, only remount the mounts we explicitly want to write to
just before operating, rename patch accordingly, reuse
do_restore_task_mnt_ns, optimize inefficient ns_remount_readonly_mounts,
and also add another exception.
v5: simplify child status check, fix log messages and brackets, do not
drop all flags but only the readonly flag
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On restore we change mounts tree topology and paths in find_remap_mounts
thus mns_is_overmounted does not account remaped overmounts. So to know
which mounts will be actually overmounted after restore we need two much
effort, better prepare these info in advance.
That also should improve performance of mnt_is_overmounted on dump,
as we reuse calculations from previous calls.
v3: make mnt_is_overmounted boolean again
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Use realloc() to change the size of the memory block pointed
to by info->source instead of allocating new memory area and
releasing the old one. If info->source is NULL then the call
is equivalent to malloc(size).
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The `show` and `exec` commands have been deprecated for some time,
and it is unlikely to be called by users. It would be better to move
them the end of the sequence of if-statements.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
The function parse_options() should return an integer 0, 1 or 2, where:
0 := Success
1 := Failure
2 := CRIU should display help text
The current behaviour always creates a warning message which shows
the return value of that function. However, when the return value
is different than 0 (Success) CRIU will fail. Since the logging is
not initialised when this message is created, it will be lost, and
therefore it can be removed completely.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Although non-cooperative userfaultfd events have been merged into the Linux
kernel since 4.11 they were racy until 4.18.
Exclude "dangerous" tests for older kernels.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Somehow in travis tests the mmap of 8K gets "rounded" down and the actual
VMA starts 4K below the returned address. This causes /proc/pid/smaps
parsing to fail.
Increasing the allocation size to 2M seems to resolve the problem and until
the root cause is identified it looks like a viable workaround.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
The functions criu_(local_)set_service_address and
criu_(local_)set_service_binary are the only functions that
do not create a copy of the given string arguments.
This may lead to problems, if the original string gets freed
but criu relies on them.
Additionally, the function criu_local_init_opts() assigns the
default service_binary now to opt->service_binary instead of
opt->service_address which is in my opinion the preferred way
since both are types of an anonymous union.
Signed-off-by: Martin Wührer <martin.wuehrer@artech.at>
Verify that enabling / disabling THP with prctl(PR_SET_THP_DISABLE) does
not change VMA flags
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Since asciidoc is based on Phyton 2, we want to move to alternative,
and a promising one is asciidoctor. This patch allows to use
asciidoctor for formatting man pages instead of asiidoc, by passing
a make option, USE_ASCIIDOCTOR=yes.
Although asciidoctor is almost compatible with asciidoc, it can
produce a man page directly from a text file without XML, which is
more efficiently. So in asciidoctor mode, we don't require xmlto.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
a2x is never used although its presence is checked mandatorily.
Let's remove this superfluous check and the unused entry.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Split the function parse_config() into smaller parts by introducing
the parse_statement(), and add more descriptive comments to improve
readability. In addition, make sure that the last element of the array
of strings 'configuration' is initialised to NULL, which is necessary
to properly count the number of elements after parsing.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
As most of the `criu_(local_)*` functions already call `strdup()`,
it is possible, to change the function signature to `const char *`.
As the struct `criu_opts` already contains a `const char *
service_binary`, also the member `service_address` is changed to
`const char`.
Additonally, also the function `criu_local_set_freeze_cgroup()` now
calls `strdup()`.
Signed-off-by: Martin Wührer <martin.wuehrer@artech.at>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
According to https://criu.org/API_compliance, the C-library
doesn't support the pageserver option.
This patch contains the functions
`criu_(local_)set_page_server_address_port()`
that allow to specify on which ip and tcp-port the pageserver
is listening.
This patch affects only the c-lib, as criu-rpc already supports the
pageserver settings.
Signed-off-by: Martin Wührer <martin.wuehrer@artech.at>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Add run as a phony target. Move .PHONY declarations next to
their targets.
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Here $(Q) is substituted with either @ or nothing, depending on
whether V is set, to either have verbose output or not. So, it does
not make sense to add another @.
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Since this part is inside "define" statement, double $ should be
used to refer to internal functions, to call the patsubst when
a define is called (rather than defined).
This should fix dependency generation for images/
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
If `criu_local_init_opts()` is applied on the same opts-object
several times, not all of the allocated memory gets freed.
Therefore, the functions `criu_(local_)free_opts()` were introduced.
These functions ensure, that opts get freed accordingly.
Furthermore, `criu_(local_)free_opts()` gets part of the c-api,
and can therefore be called by external projects too.
Additionally, with this commit `criu_local_init_opts()` now uses
`criu_local_free_opts()`, to free the opts-parameter if it was already
initalized before.
This commit also contains a fix in `send_req_and_recv_resp_sk()` which
lead to a memory leak, if criu-notifications were received.
Signed-off-by: Martin Wührer <martin.wuehrer@artech.at>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The purpose of this helper function is to perform actions common to
different interfaces, after all CRIU options have been parsed. This can
be used, for instance, to verify that a specific option was passed to
CRIU via CLI, RPC or config file.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The header "lsm.h" was added in crtools.c with commit 6af96c8
and it became unused after commit 09c131c.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The option --lsm-profile was added with commit:
6af96c8404
lsm: add a --lsm-profile flag
In LXD, we use the container name in the LSM profile. If the container name
is changed on migrate (on the host side), we want to use a different LSM
profile name (a. la. --cgroup-root). This flag adds that support.
A usage example is available in
13389b2963
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The --tcp-close option was introduced with commit
2c37042821
tcp: Add tcp-close option to restore connected TCP sockets in closed state
This options is applicable only for restore. Therefore, move the
documentation from 'dump' to 'restore'.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The --log-pid option was introduced with commit
fc7bedc50a
crtools: make to be able to split messages by pid
This option is applicable only for restore. Therefore, move the
documentation from "Common options" to "restore".
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The current behaviour of CRIU is to inherit the group leader of the
parent process when migrating a session leader (with --shell-job).
However, it is possible for a process to be group leader without being
a session leader (e.g. a shell process). In this case CRIU should
restore the original group ID of the process and inherit only the
session ID.
Closes#593
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
getsid(0) and getpgid(0) will return session ID and PGID of
the calling process.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
I received this patch from Jeff Law as a fix for build failures with the
upcoming GCC 9. The following is Jeff Law's description of the patch:
Attached you'll find the fix for criu. You'll see it's just a matter
of dropping the sp/esp clobber from the relevant asm statements. THe
details:
criu has a macro which defines an asm which appears to want to set a new
stack pointer, then directly issue a sigreturn call to the kernel. Some
variants clobber sp (aarch64, arm, x86), others do not (ppc, s390)
While the asm does indeed set a new stack pointer, we never return from
a sigreturn syscall -- at least not in the normal way. We actually
return back to the point where the process was interrupted by the
signal. So describing the affect of the asm on the stack pointer is
pedantically correct, it actually has no real effect and can just be
dropped to avoid the hard error from gcc-9.
Suggested-by: Jeff Law <law@redhat.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In commit
c1404f6671
mount: restore cwd after creating a roots yard (v2)
were introduced changes to the function cleanup_mnt_ns() that handle
the case when opts.root is set.
However, after commit
2e8970beda
mount: create a mount point for the root mount namespace in the roots yard
the cleanup_mnt_ns() function always results in error:
mnt: Can't remove the directory ...: No such file or directory
when restore fails and opts.root has been set.
Resolves#467
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The test library has functions to create tcp sockets.
Cc: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Reviewed-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Up until now any pr_* logging command (except pr_msg) was lost if
logging has not been set up (log_init()).
To make sure not logging messages are lost, vprint_on_level() now writes
all messages (except LOG_MSG) to a temporary buffer which is written
to the logging FD once that is set up.
Improved-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Error messages in linkat_hard and open_path about link errors contradict
each other, fix the wrong one.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In regular checkpoint (not "check" action) current
architecture implies that basic diag modules such as
tcp/udp and etc will be loaded. In turn raw diag in
most case is either unloaded or even not compiled in
the system.
Thus for them just zap an error (but print this information
inside log). If an application does use raw sockets in real
we will fail later when being checkpointing the sockets
itselves.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
So we would always know what is happening even
if module is nor compiled or supported.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Lets just use regular pr_perror helper prefix without
additional 'ERROR' keyword which may confuse external
tools.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
For example if diag module is not built then we should
not spam with error message but we will print an error
if only a particular socket is really used.
v2:
- continue passing @ns into error handler because it should
be balanced with receieve handler by number of arguments;
while we don't use it yet in our handlers better to reserve
it immediately for future use;
- strictly speaking probing raw diag module has not much sense
by now -- the kernel doesn't support its autoloading in some
versions; still for code consistency we should do the same
things for all modules.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
To be able to zap error messages when needed. Without error
handler we will continue printing error. This will placate
diag modules probing since they are not mandatory features.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Changes since v1:
- Refactor test case based on Andrei's comments
Changes since v2:
- Use ZDTM_FAMILY instead of AF_INET
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Show a note that when libbsd is not installed CRIU is compiled without
setproctitle() and strlcpy() support.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This patch fixes the error:
(00.074175) Error (criu/net.c:2638): Locking network failed:
iptables-restore returned -1. This may be connected to disabled
CONFIG_NETFILTER_XT_MARK kernel build config option.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Currently, we rely on the fact that nobody else is using random and
parent and child processes will get the same random values.
Now, this test fails on the fedora rawhide. There will be nothing wrong
if we will generate test messages before forking the test process.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
open_proc_pid(PROC_SELF) returns a non-service file descriptor,
but it can take a place of a target file descriptor.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The relevant test case test_rpc_with_configuration_file_overwriting_rpc()
was actually designed around the broken behaviour. It was only working
if a previous configuration file (set via environment variable in this
case) and the RPC configuration file have the same name. The test case
which tests that RPC configuration file settings are overwriting direct
RPC settings now makes sure that no other configuration file is set via
the environment variable. If it would be set, the test case would still
succeed, even with the previous patch applied. Which is and which was the
correct behaviour.
So the main reason for this change is to test the more likely use case
that the environment based configuration file and the RPC configuration
file have different names.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
While writing runc test cases to verify that runc correctly uses RPC
configuration files it became clear that some things were not working as
they are supposed to. Looking closer at the code to set log files
via RPC configuration files I discovered that the code seems wrong (at
least I did not understand it any more (or the intentions behind it)).
This code tries to simplify that logic a bit and add more comments to
make clear what the intentions of the RPC configuration file code is.
v2:
- fix existing test case to test better (more correct)
- make changes requested by Andrei
v3:
- more changes as requested by Andrei
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
By accident I found a segfault using pre-dump in combination with the
page-server. Doing the following I was able to trigger it:
* criu page-server -D /tmp/1
* criu pre-dump -t PID -D /tmp/3 --track-mem
* criu page-server -D /tmp/4 --prev-images-dir ../1
* criu pre-dump -t PID -D /tmp/3 --track-mem
--> segfault
...
(00.010090) Warn (criu/image.c:134): Failed to open parent directory
...
(00.012984) Error (criu/mem.c:318): Pid-reuse detection failed: no parent inventory, check warnings in get_parent_stats
...
(00.013037) Error (criu/mem.c:544): Can't dump page with parasite
...
(00.013955) Pre-dumping tasks' memory
(00.013966) Pre-dumping 8793
(00.014380) Transferring pages:
Segmentation fault (core dumped)
Looking in cr-dump.c at cr_pre_dump_finish(int ret) the function gets
the return code of the previous operations in 'ret' but it is
immediately overwritten and never used.
In older CRIU versions it used to be:
if (ret < 0)
goto err;
but that is gone now. So this reintroduces the check for the int
parameter given to cr_pre_dump_finish() by the function caller.
As the commands used to trigged the segfault do not make much sense the
result is still not usable and the same 'Warn' and 'Error' messages are
printed, but the segfault is gone.
V2:
* set the return value correctly
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This avoids installing .gitignore file to compel includes.
While at it, describe why this .gitignore is needed.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
As these function is never used outside of criu/mount.c
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
rmntns_root - is fd number of opened mntns root directory, these info
doesn't help to identify mntns involved in logs, show path to these
mntns instead.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Using --lazy-pages with pre-dump causes partial memory dump and it's not
the intention. The whole point of pre-dump is to keep amount of memory that
would be dumped during tasks freeze to minimum.
Disallow running pre-dump with --lazy-pages.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The macro __list_for_each is equivalent to list_for_each and it is not
used anywhere.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The criu-lazy-migration.sh was copied from criu-lazy-pages.sh and was not
updated enough to actually run zdtm.py with --lazy-migrate.
Fix it.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The lazy memory dump used by the post copy migration cleans up page pipes
and parasite from zombie tasks, although for such task they are never
initialized.
Fix it.
Signed-off-by: Mike Rapoport <rppt@linux.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Raw sockets may carry any protocol they want so
lets try them out.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Otherwise there might be a raw socket with AF_INET
family and IPPROTO_ICMPV6 protocol which surely
don't have to restore it.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
for filename in *.c; do
if sort "$filename" | uniq -d | grep include; then
echo "$filename"
fi
done
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
MAP_ANON has been deprecated, use MAP_ANONYMOUS instead.
https://lkml.org/lkml/2007/2/3/55
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Start test
Test is SUID
./socket-tcp-nfconntrack --pidfile=socket-tcp-nfconntrack.pid --outfile=socket-tcp-nfconntrack.out
Another app is currently holding the xtables lock. Perhaps you want to use the -w option?
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The test is trying to write into a closed socket and the kernel sends
SIGPIPE in this case, which is perfectly normal and should not fail the
test.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On a system with more than 10 network interfaces the link_nsid check
fails:
$ criu check --feature link_nsid
Warn (criu/cr-check.c:1237): NSID isn't supported
The function kerndat_link_nsid() uses:
nde.ifindex = 10;
This fails as there is already an interface with ifindex 10.
This patch moves the creation of the socket into the second network
namespace and the feature check succeeds.
Suggested-by: Jiri Benc <jbenc@redhat.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This reverts commit 6b0292e126.
handle_binary() is needed for preparing PIE header during compilation.
If we need to provide API for building another compel binary, probably
it should be a separate library from libcompel.{a,so}
IOW, there is no sense to have handle_binary() included into CRIU.
For CRIU it's needed only during the build to generate parasite header.
Move handle_elf() to compel binary from library, as it was previously
corrected in commit 64bb75a859 ("compel: Drop off handle-elf routines
from library").
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Libcompel supplies to the parasite PAGE_SIZE during infection.
On ppc64/aarch64 PAGE_SIZE can be different with Large pages,
under the cover it returns __page_size.
At this moment __page_size is located in criu binary, which
prevents using libcompel as .so library in other applications
than criu on ppc64/aarch64.
Export __page_size and __page_shift in libcompel.
Fixes: #572
Fixes: 2d965008d3 ("ppc64/aarch64: Dynamically define PAGE_SIZE")
Cc: Adrian Reber <areber@redhat.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reported-by: Alexey Shabalin
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Related: https://github.com/checkpoint-restore/criu/issues/577
Restoring a runc container which is running in the host's network
namespace locked the network (iptables-restore) without unlocking it.
This disables network logging if running in the host's network
namespace.
Suggested-by: Andrei Vagin <avagin@gmail.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Recently, I introduced a new mode when a service fd are not dupped into
a fixed file descriptor number. A side effect of this is that we need to
close the old descritpor if it was installed.
Fixes: d349999967 ("criu: remove all magic of service-fd when it isn't required")
In vz7 we've a slightly different code base where fields
2 and 3 are already used. So lets reserve them and move
raw member to another number.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Just like with other inet sockets simply fetch additional
data (such as ICMP) and restore it back then.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Raw sockets may have arbitrary protocol so we
need different helper to lookup socket.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
So they would pass this check.
Note because we didn't allow raw socks in can_dump_ipproto
this routine won't be reached and it's safe to modify it this
way without breaking existing tests.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
IP_FREEBIND is not supported for SOCK_RAW ipv6 sockets.
See kernel rawv6_setsockopt() for the details.
For the rest of sockets, where they begin to support it:
the actual magic happens in do_ipv6_setsockopt(), and
IPV6_ADDRFORM optname changes sk->sk_prot to refer
to tcp_prot, udp_prot and udplite_prot, which contains
link to ip_setsockopt().
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
No need to call for do_dump_opt, since these params
are already fetched.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Don't allow to proceed dumping since we don't support
raw sockets restore yet.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
To collect raw sockets we need the kernel to support raw_diag module.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
After recent update of flake8, we have a lot of e117 warnings:
test/zdtm.py:1748:5: E117 over-indented
test/zdtm.py:1751:5: E117 over-indented
test/zdtm.py:1755:6: E117 over-indented
test/zdtm.py:1757:7: E117 over-indented
test/zdtm.py:1764:6: E117 over-indented
test/zdtm.py:1766:5: E117 over-indented
test/zdtm.py:1767:6: E117 over-indented
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Recently, a kernel behaviour how siginfo is copied into user-space was
changed:
4ce5f9c9e754 ("signal: Use a smaller struct siginfo in the kernel")
According to the rt_sigqueueinfo man page, the caller should set
si_code, si_pid, si_uid, si_value and there is no guarantee about other
fields.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
So here it is -- the release with lots of new stuff and bugfixes.
Mainly, the new code is for integration with Docker and to support
modern hardware.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When migrating from old images the particular xsave member
might not be present in core-* image, which is fine we
simply left data as initial zero state.
https://jira.sw.ru/browse/PSBM-89215
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
safe_dump produces only standard YAML tags and
cannot represent an arbitrary Python object.
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This makes two zdtm test scripts python3 compatible to run
zdtm on a system without python2.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The Go bindings for CRIU and the P.Haul extension have been moved into
a separate repository.
This patch removes the following from the criu-dev branch:
- lib/go/*
- phaul/*
- scripts/travis/phaul
The removed files are available in
https://github.com/checkpoint-restore/go-criu
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
A few controllers can be merged and before this patch, criu required to
set a new root by specifying all merged controllers.
This patch allows to specify a new root for each controller separately,
but criu will check that all merged controllers will have the same path.
https://github.com/checkpoint-restore/criu/issues/544
Signed-off-by: Andrei Vagin <avagin@gmail.com>
If we want to use flock64, we have to use fcntl64. Otherwise we will get
errors like this:
ERR: file_locks07.c:49: Can't set ofd lock (errno = 22 (Invalid argument))
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@gmail.com>
It looks like, this one is no more needed.
You were a hard child, RIP.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Kernel will send signal with ABI of *syscall* that made rt_sigacation().
In sigaction_compat_abi():
> if (in_ia32_syscall())
> act->sa.sa_flags |= SA_IA32_ABI;
So, we can omit switching to ia32 mode and just call int80 like in other places.
We still need 32-bit argument for syscall (sig action pointer).
As call32_from_64() switches mode, it's .text should be placed in lower 4Gb,
which was the reason of segfault if linker places criu code above 4Gb.
Oops, my bad.
Fixes: #567
Reported-by: Andrey Vagin <avagin@gmail.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Looks like, we're missing the check which potentially can add us
some troubles.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
%ebx, %ecx aren't specified as clobbers in chk_proc_fpu(),
while asm cpuid overwrites them.
In the turn, %ebx is used as a code position by gcc now:
1661: e8 9a 00 00 00 call 1700 <__x86.get_pc_thunk.bx>
1666: 81 c3 46 68 00 00 add $0x6846,%ebx
Which results in dereferencing some ugly garbage (result of cpuid).
Let's use zdtm/lib cpuid() function instead.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Here is one of popular error, when we call fork, then run a child code
and instead of exiting from a child process, we returns from a current
function with an error code.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
There are a few patches in linux-next, which added this check:
ipc: IPCMNI limit check for semmni
ipc: IPCMNI limit check for msgmni and shmmni
Signed-off-by: Andrei Vagin <avagin@gmail.com>
cr_check() initializes root_item and calls collect_pstree_ids. It was
not designed to be called directly from a service process.
Signed-off-by: Andrei Vagin <avagin@gmail.com>
setup_opts_from_req() sets up logging and call kerndat_init().
Investigated-by: Adrian Reber <areber@redhat.com>
Fixes: 6e04f3b2dd06 ("criu: call kerndat_init() after log_init()")
Signed-off-by: Andrei Vagin <avagin@gmail.com>
When restoring a task in it's user namespace we had: "Unable to open
pages-3.img: Permission denied" when trying to open pages images for
write. (Write is needed for memory images deduplication feature to
work.)
These patch makes do_open_image open images fd through usernsd, to have
root permissions.
Also increase MAX_UNSFD_MSG_SIZE as path and metadata don't fit, and
remove a workaround in prepare_vma_ios.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Rename the local variables 'pb' to 'pbuff' to avoid conflict with the
imported 'pb' module.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Otherwise all external tty-s will share the same tty info,
what is obviously wrong.
v2: allocate a separate tty index range for externl terminals
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
In this case:
* don't need to care whether they intercept with restored file
descriptors.
* they don't copied into each restored process
* don't need to close them one by one
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Currently, we create only one external resource to check how it is
handled by criu. It is better to create more than one.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
On loaded systems running maps04 with lazy-pages takes too much time. The
same functionality is anyway covered by other tests so excluding maps04
shouldn't decrease the test coverage.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
This generates more readable data in logs.
| (00.002930) inet: Collected: ino 0xc3f15b family AF_INET type SOCK_DGRAM port 8081 state TCP_CLOSE src_addr 127.0.0.10
| (00.002980) inet: Collected: ino 0xc3f159 family AF_INET type SOCK_RAW port 1 state TCP_CLOSE src_addr 127.0.0.14
| (00.002984) inet: Collected: ino 0xc3f158 family AF_INET type SOCK_RAW port 17 state TCP_CLOSE src_addr 127.0.0.12
| (00.002988) inet: Collected: ino 0xc3f156 family AF_INET type SOCK_RAW port 255 state TCP_CLOSE src_addr 0.0.0.0
| (00.003439) inet: Collected: ino 0xc3f15a family AF_INET6 type SOCK_RAW port 58 state TCP_CLOSE src_addr ::
| (00.003449) inet: Collected: ino 0xc3f157 family AF_INET6 type SOCK_RAW port 255 state TCP_CLOSE src_addr ::
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
The tun files may have same names but different
net namespace so consider ns_id when searching
for particluar tun device name.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Opening tun device is tricky: the net device
is allocated from current net namespace, thus
we should set it first, otherwise all tuns
which live in nested net namespace get moved
to the toplevel one.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
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 <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
Use __future__ imports to keep this working for python2
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@gmail.com>
CPython currently uses a reference-counting scheme with (optional)
delayed detection of cyclically linked garbage, which collects most
objects as soon as they become unreachable, but is not guaranteed to
collect garbage containing circular references.
Some objects contain references to "external" resources such as open
files. It is understood that these resources are freed when the object
is garbage-collected, but since garbage collection is not guaranteed to
happen, such objects also provide an explicit way to release the
external resource, usually a close() method.
Programs are strongly recommended to explicitly close such objects.
Reference: https://docs.python.org/3.6/reference/datamodel.html
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add hostname resolution in setup_tcp_client(). This change allows a
valid hostname to be provided as value for --address option when
connecting to page server.
This change is needed for the following path which removes
setup_TCP_client_socket() from img-proxy.c. In this function the
hostname resolution was implemented using gethostbyname()
However, here we use `getaddrinfo` instead because gethostbyname() is
marked obsolescent in POSIX.1-2001 and is removed in POSIX.1-2008
specifications.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When --remote-lazy-pages is used the address option was not specified.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The function `setup_TCP_server_socket` (defined in img-remote.c) and
`setup_tcp_server` (defined in util.c) have very similar functionality.
Replace setup_TCP_server_socket() with setup_tcp_server() to reduce
code duplication and to enable IPv6 support for the image-cache action
of CRIU.
We set SO_REUSEADDR flag to allow reuse of local addresses.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't have rights to print anything into standard descriptors
and we want to have all output in a specified log file.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Service descriptors are a set of file descriptors which isn't
intercepted with restored file descriptors.
In all cases, when we don't need to restore file descriptors, we can
skip all magic of service-fd and just save descriptor numbers in a
static array.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently, install_service_fd() always creates a new file descriptor,
but it is going to be reworked to reuse a file descriptor when it is
possible.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For a long time we've been demanding from cpus to be compatible
on fpu frame level, but growing list of cpu features triggers
inability for restored programs to proceed after restore due
to specific intructions execution (such as avx2). Note the
fpu frame may carry same size but not on instruction level
where SIGILL may happen after the restore.
Thus lets require instruction mode to be set and verified by default.
Still one can drop this option via command line or rpc request.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since we're using bintmaps for options don't exit early
if --cpu-cap=ins specified because there might be a
combination of options.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since now validation is bit based there is no longer need to
exit early if fpu matches, we rather need over all possible
options where several capability modes can be set.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To preserve backward compatibility because
strict mode now lays under own block.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Current scheme of when to write and verify cpuinfo
images is unclear: we define default mode to 'fpu'
and this implies that no cpuinfo image get written
on dump and read on restore. In turn if 'cpu' or
'ins' mode specified in command line we write and
verify this image.
This is all wrong -- we need to produce image if
any mode ecxept 'none' is specified. The 'none'
mode is designed exactly for skipping cpuinfo
image production or verification.
Because any non-default mode requires explicit
--cpu-cap option to be passed we can use this
and setup new CPU_CAP_IMAGE telling criu to
write or read this image.
Note the default mode doesn't break backward
compatibility because by default we don't
write or read the image at all.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It should be there from the beginning but happen to escape.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
xsave sizes should sit in fpu capability block because
instruction and strick mode checkig is a different
thing.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Usually people simply leave cpu checkin in default
mode (which is fpu level) but idea was to be able
to compose a mixture of settings, for this sake
CPU_CAP_ constants are bit shifts. Thus use bitwise
operator for this.
Same time define CPU_CAP_ as bit shifts explicitly
and use explicit CPU_CAP_NONE compare where needed.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Keep xsave sizes in image to be sure that on restore the application
won't override memory out of xsave frame size if been calling xsave
instruction directly.
Here are some details: while been testing vz7 containers migration
we've noticed that sometime applications do crash after restore,
what is worse such execution abort may happen not immediately
after the restore but after passing some time. After spending
a lot of time we discovered that it is due to the fact that
the migration is directed from an old cpu to a modern one
which has extensions such as mpx. In result libc has cached
small xsave size and then after restore any direct call to
xsave instruction overwrite memory which is allocated with
size less than needed.
Thus we save xsave frame size in image and require it to
match to prevent such situation.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmaill.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Before fix issubpath("./zdtm/static/mntns_shared_vs_private.test",
"./") returned false, though should return true.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
colon operators are there obviously by mistake instead of semicolons
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As mnt_roots always has a slash at the beginning we don't need another:
(00.156035) 1: mnt: Move the root to //tmp/.criu.mntns.ZKVJHl/15-0000000000
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
for i in $(find . -name "*.[ch]" -type f); do
sed -i 's/\(pr_warn(".*[^n]\)\("[),]\)/\1\\n\2/' $i
done
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In RPC mode the log_level was always reset to the default log level of 2, if no
configuration file was used.
This saves the log level set via RPC in opts.log_level and a configuration file
can overwrite it later, but if it is only set via RPC this value is not ignored
now.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The -c and -f options were introduced on December 2011 with
commit 485c4b50d1
show: Rework show procedure
Added
- ability to parse every single file crtools
understands via magic number
- dumped memory pages can be rendered in two
modes -- as a simple set of pages' virtual addresses
or in hexdummp fashion (via -c command line key).
For example
./crtools -s -c -f pages-2557.img
CR_FD_PAGES: pages-2557.img
----------------------------------------
7fffb44ace20: 00 00 00 00 00 00 00 00 00 00 00 74 65 73 74 2f |. . . . . . . . . . . t e s t / |
7fffb44ace30: 74 65 73 74 2d 73 69 67 61 63 74 69 6f 6e 00 48 |t e s t - s i g a c t i o n . H |
7fffb44ace40: 4f 53 54 4e 41 4d 45 3d 6c 6f 63 61 6c 68 6f 73 |O S T N A M E = l o c a l h o s |
7fffb44ace50: 74 2e 6c 6f 63 61 6c 64 6f 6d 61 69 6e 00 54 45 |t . l o c a l d o m a i n . T E |
The -p/--pid option was added on April 2013 with
commit 73d7e283a7
show: Filter -D output with --pid option
Show only image info relevant to given pid. Also reuse
the introduced --pid argument for exec action.
And the -F option was introduced on December 2013 with
commit 7ab8a3261b
show: Implement simple images filtering
The -F|--fields option specifies which fields (by name, comma
separated) should be printed.
For nested fields all names in path should be specified.
All four options were used in combination with the deprecated --show
command which has been decommissioned on February 2016 with
commit a501b4804b
show: Remove deprecated code
The 'show' action has been deprecated since 1.6, let's finally drop it.
The print_data() routine is kept for yet another (to be deprecated too)
feature called 'criu exec'.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
>>> CID 164715: (BUFFER_SIZE_WARNING)
>>> Calling strncpy with a maximum size argument of 16 bytes on
destination array "thread_args[i].comm" of size 16 bytes might
leave the destination string unterminated.
3473 strncpy(thread_args[i].comm, core->tc->comm, TASK_COMM_LEN);
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When zdtm.py is executed with `list` sub-command the 'criu_bin'
option is not defined and criu.available() fails.
$ python test/zdtm.py list
Traceback (most recent call last):
File "test/zdtm.py", line 2243, in <module>
criu.available()
File "test/zdtm.py", line 1185, in available
if not os.access(opts['criu_bin'], os.X_OK):
KeyError: u'criu_bin'
However, we don't need to check the existence of criu_bin
unless we use the `run` action.
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is especially important when accessing a hash --
there must be no negative indices ever.
https://jira.sw.ru/browse/PSBM-82945
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In commit 23b769498c ("dump: optimize dead_pid_conflict by searching
in rbtree") we'd replaced for_each_pstree_item and thread walk search
with pstree_pid_by_virt (rb-tree search). The latter already found us
the thread with conflicting pid if it exists, the only thing left is to
skip if the thread is also a main thread of the thread group (as it was
before patch). But some leftover left which checks something wrong: we
index ->threads array with "i", but "i" is not a number of the thread
it is a number of current dead pid.
Not sure if it helps with the initial bug and duplicates, but it might:
https://jira.sw.ru/browse/PSBM-55217
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This can happen when running in user namespace with auto-dedup enabled.
Right now this means auto-dedup gets disabled.
Signed-off-by: Pawel Stradomski <pstradomski@google.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
call variables of type RemapFilePathEntry - "rpe" everywhere, similar as
we already name them in oher places
while on it remove unused second argument of open_remap_linked
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After running criu test, docker on the node becomes unusable, as it is
confused by our leftover cgroups. Surely docker should be fixed to
ignore custom cgroups (https://github.com/moby/moby/issues/37601), but
we should not leave them after test also.
v2: rmdir the holder only if it exists, remove racy wait and remove
wrongly added cleanup method in class criu
v3: bring back missed semicolon
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case if pipe buffers are full the splicing
may wakeup reader first with incomplete data
transfer. Thus splice data in cycle.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
05:57:35.640: 1238: FAIL: fork.c:80: Task 16275 didn't exit (errno = 10 (No child processes))
There is no info about the killing signal in logs, add it.
https://jira.sw.ru/browse/PSBM-87579
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The stack pointers will be later use by the memory dump to ensure that
current stack pages are not treated as lazy.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Currently parasite_thread_ctl for non-leader threads is initialized after we
stop the compel daemon. Moving this initialization earlier will allow us to
make stack pointers of all threads available during memory dump.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
We need to know what are stack pointers of every thread to ensure that the
current stack page will not be treated as lazy.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
This is obviously not a real check. This only exists, so that CRIU
clients/users can check if this CRIU version supports the external
network namespace feature. Theoretically the CRIU client or user could
also parse the version, but especially for CLI users version comparison
in the shell is not easy.
This feature check does not exist for RPC as RPC has a special version
call which does not require string parsing and the external network
namespace feature is available for all CRIU versions newer than 3.9.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since the processes and fds are restored from images in the increasing
order, and they are stored in sorted lists, CRIU always needed (at least
in my experiments) to traverse the whole list before inserting them.
With this change, lists are traversed in reverse, so the fds should be
inserted immediately.
Acked-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Radoslaw Burny <rburny@google.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The latest patches to cr-service.c broke compilation with gcc-8:
criu/cr-service.c: In function ‘setup_opts_from_req’:
criu/cr-service.c:323:3: error: ‘strncpy’ specified bound 4096 equals destination size [-Werror=stringop-truncation]
strncpy(images_dir_path, opts.imgs_dir, PATH_MAX);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
criu/cr-service.c:343:3: error: ‘strncpy’ specified bound 4096 equals destination size [-Werror=stringop-truncation]
strncpy(work_dir_path, opts.work_dir, PATH_MAX);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
cc1: all warnings being treated as errors
This fixes the errors by specifying the strncpy() size as 'PATH_MAX - 1'.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With this commit it is possible to specify a configuration file via
RPC. In python this would look like this:
req.opts.config_file = 'path/to/config_file'
With this commit CRIU's configuration file handling works like this:
* apply_config(global_conf)
* apply_config(user_conf)
* apply_config(environment variable)
* apply_config(config file via CLI)
* apply_rpc_options() or apply_cli_options()
* apply_config(rpc_conf) (only for RPC)
This is at least (probably) the third iteration of the RPC configuration
file code and it still is complicated.
Most CRIU options are correctly used by just writing the new values to
the corresponding fields of the opts structure. For the RPC case there
are, however, a few options (output, work_dir, imgs_dir) which need
special handling.
So the RPC configuration file is parsed twice. First time to get output,
work_dir and imgs_dir. Once those are read and correctly used, the RPC
code overwrites all options again by values set by the RPC interface. At
the end the RPC configuration file is read a second time and finally
overwrites the values set via RPC.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This test checks the following things:
* Does configuration file parsing work at all.
* Does the parser detect wrong options.
* Does the configuration file work via RPC.
* Do the configuration file options not overwrite the RPC settings in
the default setup.
* Is it possible to tell CRIU to prefer the configuration file via RPC.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When CRIU is started in RPC mode ('criu swrk') it used to ignore all
command-line options and configuration files. This moves the jump to RPC
mode after the configuration file parsing to enable configuration.
With this configuration files are now also evaluated in RPC mode and it
is possible to change the behavior of CRIU via the configuration file if
used via RPC.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With this it is possible to point the environment variable
CRIU_CONFIG_FILE to a CRIU configuration file.
The order the configuration files are evaluated now is:
1. global (/etc/criu/default.conf)
2. user ($HOME/.criu/default.conf)
3. CRIU_CONFIG_FILE
4. --config FILENAME
5. CLI
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With the previous change to dynamically allocate memory for each
possible configuration source (three different configuration files, CLI,
RPC) the char * options can no longer directly point to the character
strings extracted by getopt() as the memory might be free'd at some
point. This introduces a macro to set the char * options which first
does a xfree() and then a xstrdup().
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The code to read and parse configuration files was writing the result of
the global configuration file to one variable and the result from the
configuration file in the user's home to another variable:
char **global_conf = NULL;
char **user_conf = NULL;
With this change the code now uses dynamic memory allocation to handle
the different configuration files.
It used to be:
* parse global config
* parse user config
* evaluate global config
* evaluate user config
* evaluate CLI
And now it is:
* parse global config
* evaluate global config
* parse user config
* evaluate user config
* evaluate CLI
This change is in preparation for the upcoming setting of a
configuration file via environment variable and RPC configuration file
usage.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This just moves the functions init_opts() and deprecated_ok() also to
config.c as that is where most of the option and configuration setup
and handling is done today.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The variable show_dump_file and show_fmt are assigned but never used,
this remove the assignment. The CLI option still exists to not break the
user interface. It exists, but it is unused.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This removes the code around '--pid, -p' which is not used at all. The
command-line option is still available to not break CRIU users, but as
the result has not been used, just remove the code assigning it.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This moves the whole getopt setup and analysis out of main() into its
own function in config.c.
The main motivation for this change is to be able to call getopt parsing
and configuration file parsing also from the RPC code path.
In one of the discussion emails about configuration files in CLI and RPC
mode the following architecture was proposed:
apply_config(global_conf)
apply_config(user_conf)
apply_config(pre_conf)
parse_command_line()
apply_rpc_options()
apply_config(post_conf)
And especially for the last step the getopt parsing needs to be out of
main() and callable from the RPC code path.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CC criu/cr-restore.o
criu/cr-restore.c:3470:22: error: address of array 'thread_args[i].comm' will always evaluate to 'true' [-Werror,-Wpointer-bool-conversion]
if (thread_args[i].comm)
~~ ~~~~~~~~~~~~~~~^~~~
1 error generated.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 190774 (#1 of 1): Out-of-bounds access (OVERRUN)
5. overrun-buffer-arg: Overrunning array addr.sun_path of 108 bytes by
passing it to a function which accesses it at byte offset 4094 using
argument ui->ue->name.len (which evaluates to 4095).
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 190775 (#1 of 1): Dereference before null check (REVERSE_INULL)
check_after_deref: Null-checking m->parent suggests that it may be null,
but it has already been dereferenced on all paths leading to the check.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 190777 (#1 of 1): Resource leak (RESOURCE_LEAK)
15. leaked_handle: Handle variable server_fd going out of scope leaks the handle.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The host compel-host-bin must be built before
criu, same time the criu itself should not depend
on libcompel or plugins because they are the part
of the compel package.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
They were occasionally kept in obj-y.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Thus to choose which deps to include, for example if only
particular file is being build there is no need to include
any other deps.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Thus will include hostprogs deps only if requested.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We fully support xsaves, so no need for noxsaves temporary
option anymore.
This reverts commit ba93feb5f0.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We fully support xsaves now, so no need for
warning or any other message.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
arm's cpu code is the same as aarch64, so use
the symlink.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
cpu extensions (such as avx-512) require bigger xsave
area to keep fpu registers set, so we allocate a page
per process to keep them all. On checkpoint we parse
runtime fpu features and dump them into an image and
do reverse on restore procedure.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This feature will allow to catch incapability early
if present in image.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- externd compel_cpuinfo_t to keep all fpu information
neded for xsaves mode
- fetch xsaves data in compel_cpuid
All this will allow us to extend criu to support
avx-512 intructions.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We're printing messages before the log file
is set up, so instead of keeping silence lets
print data in default outputs.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This reduces memory usage if image files are stored on tmpfs.
Signed-off-by: Pawel Stradomski <pstradomski@google.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In resolve_shared_mounts there are cases when we have m->master_id > 0
but m->mnt_master is not set, it happens for cases where we have no
access to master mount, for instance CT root m->parent==NULL or when
mount is external. In can_mount_now for such master mounts we don't
need to check mounted state also, so just use "if(mi->mnt_master)"
condition instead of "if(mi->master_id > 0)" to fix segfault.
https://jira.sw.ru/browse/PSBM-86978
Program terminated with signal 11, Segmentation fault.
0x000000000046328b in can_mount_now (mi=0x2155970) at criu/mount.c:2699
2699 list_for_each_entry(c, &mi->mnt_master->children, siblings)
(gdb) p mi->mnt_master
$2 = (struct mount_info *) 0x0
Fixes commit 3a02362c5b ("mount: fix can_mount_now to wait children of
master's share properly")
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Running 'criu dump -t <PID>' with a configuration file under valgrind
where <PID> does not exist, gives:
==14336== 600 bytes in 5 blocks are definitely lost in loss record 5 of 5
==14336== at 0x4C29BC3: malloc (vg_replace_malloc.c:299)
==14336== by 0x5D387A4: getdelim (in /usr/lib64/libc-2.17.so)
==14336== by 0x439829: getline (stdio.h:117)
==14336== by 0x439829: parse_config (config.c:69)
==14336== by 0x439CB2: init_configuration.isra.1 (config.c:159)
==14336== by 0x439F75: init_config (config.c:212)
==14336== by 0x439F75: parse_options (config.c:487)
==14336== by 0x42499F: main (crtools.c:140)
==14336== LEAK SUMMARY:
==14336== definitely lost: 600 bytes in 5 blocks
With this patch:
==17892== LEAK SUMMARY:
==17892== definitely lost: 0 bytes in 0 blocks
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It works like other external resources.
A user specify which namespaces are external and have not to be dumped.
On restore, the user gives file descriptors to preconfigured namespaces.
How to use:
dump:
--external net[INO]:KEY
restore:
--inherit-fd fd[NSFD]:KEY
The test script contains more details how to use this:
test/others/netns_ext/run.sh
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to know which namespaces are external to restore them properly.
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We already check (root, mountpoint) pairs preserve, do the same for
(root, mountpoint, shared, slave) fours.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When CRIU is called for a first time and the /run/criu.kdat file does
not exists, the following warning is shown:
Warn (criu/kerndat.c:847): Can't load /run/criu.kdat
This patch is replacing this warning with a more appropriate debug message.
File /run/criu.kdat does not exist
Signed-off-by: Radostin Stoyanov <rstoyanov1@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If we fail to create temporary directory for doing a clean mount we can
make mount clean reusing the code which enters new mountns to umount
overmounts. As when last process exits mntns all mounts are implicitly
cleaned from children, see in kernel source - sys_exit->do_exit
->exit_task_namespaces->switch_task_namespaces->free_nsproxy
->put_mnt_ns->umount_tree->drop_collected_mounts->umount_tree:
/* Hide the mounts from mnt_mounts */
list_for_each_entry(p, &tmp_list, mnt_list) {
list_del_init(&p->mnt_child);
}
Fixes commit b6cfb1ce29 ("mount: make open_mountpoint handle overmouts
properly")
https://github.com/checkpoint-restore/criu/issues/520
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Create a tree of shared mounts where shared mounts have different sets
of children (while having the same root):
First share1 is mounted shared tmpfs and second share1/child1 is mounted
inside, third share1 is bind-mounted to share2 (now share1 and share2
have the same shared id, but share2 has no child), fourth share1/child2
is bind-mounted from share1, and also propagated to share2/child2 (now
all except share1/child1 have the same shared id), fifth share1/child3
is mounted and propagates inside the share.
Finally we have four mounts shared between each other with different
sets of children mounts, and even more two of them are children of
another two:
495 494 0:62 / /zdtm/static/non_uniform_share_propagation.test/share1 rw,relatime shared:235 - tmpfs share rw
496 495 0:63 / /zdtm/static/non_uniform_share_propagation.test/share1/child1 rw,relatime shared:236 - tmpfs child1 rw
497 494 0:62 / /zdtm/static/non_uniform_share_propagation.test/share2 rw,relatime shared:235 - tmpfs share rw
498 495 0:62 / /zdtm/static/non_uniform_share_propagation.test/share1/child2 rw,relatime shared:235 - tmpfs share rw
499 497 0:62 / /zdtm/static/non_uniform_share_propagation.test/share2/child2 rw,relatime shared:235 - tmpfs share rw
500 495 0:64 / /zdtm/static/non_uniform_share_propagation.test/share1/child3 rw,relatime shared:237 - tmpfs child3 rw
503 497 0:64 / /zdtm/static/non_uniform_share_propagation.test/share2/child3 rw,relatime shared:237 - tmpfs child3 rw
502 499 0:64 / /zdtm/static/non_uniform_share_propagation.test/share2/child2/child3 rw,relatime shared:237 - tmpfs child3 rw
501 498 0:64 / /zdtm/static/non_uniform_share_propagation.test/share1/child2/child3 rw,relatime shared:237 - tmpfs child3 rw
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
These also fixes false-propagation problem of the mount to itself if it
is in parent's share.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
1) redo waiting for parents of propagation group to be mounted using
pre-found propagation groups
2) for shared mount wait for children of that shared group which has no
propagation in our shared mount
(2) - effectively is a support of non-uniform shares, that means two
mounts of shared group can have different sets of children now - we will
mount them in the right order, but propagate_mount and validate_shared
are still preventing c/r-ing such shares, will fix the former and remove
the latter in separate(next) patches.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
These information will help improving the restore of tricky mounts
configurations.
Function same_propagation_group checks if two mounts were created
simultaneousely through shared mount propagation, and the main part of
these - they should be in exaclty the same place inside the share of
their parents.
Function root_path_from_parent prints the mountpoint path
relative to the root of the parent's share, by first substracting
parent's mountpoint from our mountpoint and second prepending parents
root path (relative to the root of it's file system), e.g:
id parent_id root mountpoint
1 0 / /
2 1 / /parent_a
3 1 /dir /parent_b
4 2 / /parent_a/dir/a
5 3 / /parent_b/a
(Let 2 and 3 be a shared group)
For mount 4 root_path_from_parent gives:
"/parent_a/dir/a" - "/parent_a" == "/dir/a"
"/" + "/dir/a" == "/dir/a"
For mount 5:
"/parent_b/a" - "/parent_b" == "/a"
"/dir" + "/a" == "/dir/a"
So mounts 4 and 5 are a propagation group.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We should not use ->bind link for checking master's children. As if we
have two slaves shared between each other, the one mounted first will
replace ->bind link for the other - that will break restore.
Also while on it, if we do not want doubled mounts and want to
prohibit propagation to slaves on restore we likely want all children of
the whole master's share mounted before slave.
JFYI: Actually these restriction is very strict and some cases will fail
to restore, for instance (hope nobody does so):
mkdir /test
mount -t tmpfs test /test
mount --make-private /test
mkdir /test/{share,slave}
mount -t tmpfs share /test/share --make-shared
mount --bind /test/share/ /test/slave/
mount --make-slave /test/slave
mount --make-shared /test/slave
mkdir /test/share/slave
mount --bind /test/slave/ /test/share/slave/
cat /proc/self/mountinfo | grep test
524 612 0:69 / /test rw,relatime - tmpfs test rw
570 524 0:73 / /test/share rw,relatime shared:879 - tmpfs share rw
571 524 0:73 / /test/slave rw,relatime shared:942 master:879 - tmpfs share rw
602 570 0:73 / /test/share/slave rw,relatime shared:942 master:879 - tmpfs share rw
603 571 0:73 / /test/slave/slave rw,relatime shared:943 master:942 - tmpfs share rw
Here 603 is a propagation of 602 from master 570 to slave 571, and it is
the only way to get such a mount as 571 and 602 are in one shared group
now and all later mounts to them will propagate between them and create
dublicated mounts. So to create real 603 without dups we need to have
/test/slave mounted before /test/share/slave, which contradicts with
current assumption.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
See more detailed explanation inside in-code comment.
note: Actually before we remove validate_mounts (later in these
patchset) we likely won't get to these check and fail earlier, as having
children collision implies shared mounts with different sets of
children.
note: from v4.11 and ms kernel commit 1064f874abc0 ("mnt: Tuck mounts
under others instead of creating shadow/side mounts.") there will be no
more mount collision.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
We use fdstore intensively for example when handling
bindmounted sockets and ghost dgram sockets. The system
limit for per-socket queue may not be enough if someone
generate lots of ghost sockets (150 and more as been
detected on default fedora 27).
To make it operatable lets unlimit fdstore queue size
on startup.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we are dumping epoll and one of target fd is been
duped we can reuse already collected fds rbtree to find
proper target. We handle it in a lazy way:
- try use plain regular bsearch first, in case of all
targets are not duped we checkpoint epoll immediately
- if bsearch failed we put this epoll entry into a queue
and run its dumping later when all other files in the
process are already dumped. At this moment fds tree
should already has all target files in rbtree thus
we can simply lookup for it
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is used in files tree generation so we will need
reuse for epoll sake.
Also use the whole 64 bit offset to shuffle bits more.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To find target files with help of our collected
rbtree.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If we can't find target file descriptor we should
exit on dump with error instead of skipping it.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We will use them to fast lookup of targets files.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To figure out efd:tfd mapping easier by reading the logs.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When target file obtained from epoll fdinfo (internally the
kernel keeps only file _number_ inside) we have to check its
identity to make sure it is exactly one which has been added
into epoll engine. The only proper way is to use kcmp syscall.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we are checkpoiting epoll targets we assuming that this target
file is belonging to the process we are on. This is of course not
true. Without kernel support the only thing we can do is compare
fd numbers with ones present in epoll fdinfo. When fd numer match
we assume that it indeed the file which has been added into epoll.
This won't cover the case when file has been moved to some other
number and new one is reopened instead of it. Such scenario will
trigger false positive and we can't do anything about.
In next patches with kernel help we will make precise check for
files identity.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In epoll dumping we will need the whole set of fds to investigate
the targets, so pass this parameter down to epoll code.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We will need it to make sure the target files in epolls are present
in current process.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- switch to use uintX type (just to drop uX finally,
it doesn't worth to carry this type)
- instead of including huge util.h rather include the
files which are really needed: log, xmalloc, compiler
and bug
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Before this patch we used flock to order task creation,
but this way is not good. It took 5 syscalls to synchronize
a creation of a single child:
1)open()
2)flock(LOCK_EX)
3)flock(LOCK_UN)
4)close() in parent
5)close() in child
The patch introduces more effective way for synchronization,
which executes 2 syscalls only. We use last_pid_mutex,
and the syscalls number sounds definitely better.
v2: Don't use flock() at all
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I think, we should warn a user when we can't C/R compatible
applications. That's valid for different than x86 archs.
Let's correct the message the way it'll suit non-x86.
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When a non-root user runs "criu restore" and criu has the suid bit,
a process will run with non-zero uid and gid.
Before the 4.13 kernel (4d28df6152aa "prctl: Allow local CAP_SYS_ADMIN
changing exe_file"), PR_SET_MM_EXE_FILE fails if uid or gid isn't zero.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Install sudo, create test user with ID 1000, install bash,
fix pidfile creation and pidfile chmod.
v2:
* use sleep to give the criu daemon some time to start up
v3:
* Andrei is of course right and sleep is not good solution.
After adding --status-fd support to criu service, this
is how we now detect that criu is ready.
v4:
* This was much more complicated than expected which is related
to the different versions of the tools on the different travis
test targets. There seems to be a bug in bash on Ubuntu
https://lists.gnu.org/archive/html/bug-bash/2017-07/msg00039.html
which prevents using 'read -n1' on Ubuntu. As a workaround
the result from CRIU's status FD is now read via python.
Another problem was discovered on alpine with the loop restore test.
CRIU says to use setsid even if the process is already using setsid.
As a workaround, still with setsid, this process is now using
shell-job true for checkpoint and restore.
Parts of v2 have been committed before. So the changes from this commit
are partially already in another commit.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Make the --status-fd option also work in 'criu service' mode to avoid
race conditions during testing.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Install sudo, create test user with ID 1000, install bash,
fix pidfile creation and pidfile chmod.
v2:
* use sleep to give the criu daemon some time to start up
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This extends the test.py to also run the RPC command VERSION via 'criu
service'. It was already running using 'criu swrk'.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In this directory there are various test cases using CRIU in RPC mode
(or SWRK mode).
This fixes the broken tests by moving the start of 'criu service' from
run.sh to the Makefile as the test cases is running using "sudo -g
'#1000' -u '#1000'" and the PID file created by CRIU can only be read by
the root user. If starting the 'criu service' before run.sh the PID file
still can be changed to 0666 and fixing the test script.
This also adds version.py to the test cases that are executed.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Return an error if we meet unexpected parameters in a config file
Cc: Veronika Kabatova <vkabatov@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now we rely on scanf, that it will initializes a pointer to NULL, when
it fails to parse a string, but I can't find in a man page, that it has
to do this.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of pre-parsing command line twice, one time to detect -h/--help and
another time to find config file parameter, check for both in one pass.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When config parsing was split into a separate part the handling of
-h/--help option during init_config was broken. Fix it.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
s/first_count/global_cfg_argc
s/second_count/user_cfg_argc
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently kerndat_init() runs before command line parsing and running
simple 'criu --version' command may produce something like:
Warn (criu/kerndat.c:847): Can't load /run/criu.kdat
Error (criu/util.c:842): exited, status=3
Error (criu/util.c:842): exited, status=3
Write 4294967295 to /proc/self/loginuid failed: Operation not permittedWarn
(criu/net.c:2732): Unable to get socket network namespace
Warn (criu/net.c:2732): Unable to get tun network namespace
Warn (criu/sk-unix.c:213): sk unix: Unable to open a socket file:
Operation not permitted
Error (criu/net.c:3023): Unable create a network namespace: Operation not
permitted
Warn (criu/net.c:3069): NSID isn't reported for network links
Version: 3.6
GitID: v3.6-611-g0b27d0a
Group early calls to kerndat_* and init_service_fd calls into a function
and call this function after the command line parsing is finished.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Creating a test for verifying configuration parsing feature. The
test is created by reusing already present inotify_irmap test.
Because of addition of default configuration files, --no-default-config
option is added to zdtm.py to not break the test suite on systems with
these files present.
Signed-off-by: Veronika Kabatova <vkabatov@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Implementation changes for usage of simple configuration files. Before
parsing the command line options, either default configuration files
(/etc/criu/default.conf, $HOME/.criu/default.conf; in this order) are
parsed, or a specific config file passed by the user. Two new options are
introduced: "--config FILEPATH" option allows users to specify a single
configuration file they want to use; and "--no-default-config" option to
forbid the parsing of default configuration files. Both options are to be
passed only via the command line.
Usage of configuration files is not mandatory to keep backwards
compatibility. The implementation of this feature tries to be compatible
with command line usage -- the user should get the same results whether
he passes the options (in the right order of parsing) on command line or
writes them in config files. This allows the user to:
1) Override boolean options if needed
2) Specify partial configuration for options that are possible to pass
several times (e.g. "--external"), and pass the rest of the options
based on process runtime by command line
Configuration file syntax allows comments marked with '#' sign, the rest
of the line after '#' is ignored. The user can use one option per line
(with argument supplied on the same line if needed, divided with whitespace
characters), the options are the same as long options (without the "--"
prefix used on command line).
Configuration file example (syntax purposes only, doesn't make sense):
$ cat ~/.criu/default.conf
tcp-established
work-dir /home/<USERNAME>/criu/work_directory
extra # inline comment
no-restore-sibling
tree 111111
Signed-off-by: Veronika Kabatova <vkabatov@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
criu/image-desc.c | 4 ++--
criu/image.c | 4 ++--
criu/include/image.h | 1 +
3 files changed, 5 insertions(+), 4 deletions(-)
In order to prepare for remote snapshots (possible with Image Proxy and Image
Cache) the O_FORCE_LOCAL flag is added to force some images not to be remote
and stay as local files in the file system.
Signed-off-by: Rodrigo Bruno <rbruno@gsd.inesc-id.pt>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We'll need some docs :) bu the API is
criu := MakeCriu()
criu.Dump(opts, notify)
criu.Restore(opts, notify)
criu.PreDump(opts, notify)
criu.StartPageServer(opts)
where opts is the object from rpc.proto, Go has almost native support
for those, so caller should
- compile .proto file
- export it and golang/protobuf/proto
- create and initialize the CriuOpts struct
and notify is an interface with callbacks that correspond to criu
notification messages.
A stupid dump/restore tool in src/test/main.go demonstrates the above.
Changes since v1:
* Added keep_open mode for pre-dumps. Do use it one needs
to call criu.Prepare() right after creation and criu.Cleanup()
right after .Dump()
* Report resp.cr_errmsg string on request error.
Further TODO:
- docs
- code comments
travis-ci: success for libphaul (rev2)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
So, here's the next test that just enumerates all possible states and checks
that CRIU C/R-s it well. This time -- pipes. The goal of the test is to load
the fd-sharing engine, so pipes are chosen, as they not only generate shared
struct files, but also produce 2 descriptors in CRIU's fdesc->open callback
which is handled separately.
It's implemented slightly differently from the unix test, since we don't want
to check sequences of syscalls on objects, we need to check the task to pipe
relations in all possible ways.
The 'state' is several tasks, several pipes and each generated test includes
pipe ends sitting in all possible combinations in the tasks' FDTs.
Also note, that states, that seem to be equal to each other, e.g. pipe between
tasks A->B and pipe B->A, are really different as CRIU picks the pipe-restorer
based in task PIDs. So whether the picked task has read end or write end at
his FDT makes a difference on restore.
Number of tasks is limited with --tasks option, number of pipes with the
--pipes one. Test just runs all -- generates states, makes them and C/R-s
them. To check the restored result the /proc/pid/fd/ and /proc/pid/fdinfo/
for all restored tasks is analyzed.
Right now CRIU works OK for --tasks 2 --pipes 2 (for more -- didn't check).
Kirill, please, check that your patches pass this test.
TODO:
- Randomize FDs under which tasks see the pipes. Now all tasks if they have
some pipe, all see it under the same set of FDs.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
By exhaustive testing I understand a test suite that generates as much
states to try to C/R as possible by trying all the possible sequences
of system calls. Since such a generation, if done on all the Linux API
we support in CRIU, would produce bazillions of process, I propose to
start with something simple.
As a starting point -- unix stream sockets with abstract names that
can be created and used by a single process :)
The script generates situations in which unix sockets can get into by
using a pre-defined set of system calls. In this patch the syscalls
are socket, listen, bind, accept, connect and send. Also the nummber
of system calls to use (i.e. -- the depth of the tree) is limited by
the --depth option.
There are three things that can be done with a generated 'state':
I) Generate :) and show
Generation is done by recursively doing everything that is possible
(and makes sence) in a given state. To reduce the size of the tree
some meaningless branches are cut, e.g. creating a socket and closing
it right after that, creating two similar sockets one-by-one and some
more.
Shown on the screen is a cryptic string, e.g. 'SA-CX-MX_SBL one,
describing the sockets in the state. This is how it can be decoded:
- sockets are delimited with _
- first goes type (S -- stream, D --datagram)
- next goes name state (A -- no name, B with name, X socket is not in
FD table, i.e. closed or not yet accepted)
- next may go letter L meaning that the socket is listening
- -Cx -- socket is connected and x is the peer's name state
- -Ixyz -- socket has incoming connections queue and xyz are the
connect()-ors name states
- -Mxyz -- socket has messages and xyz is senders' name states
The example above means, that we have two sockets:
- SA-CX-MX: stream, with no name, connected to a dead one and with a
message from a dead one
- SBL: stream, with name, listening
Next printed is the sequence of system calls to get into it, e.g. this
is how to get into the state above:
socket(S) = 1
bind(1, $name-1)
listen(1)
socket(S) = 2
connect(2, $name-1)
accept(1) = 3
send(2, $message-0)
send(3, $message-0)
close(3)
Program has created a stream socket, bound it, listened it, then
created another stream socket, connected to the 1st one, then accepted
the connection sent two messages vice-versa and closed the accepted
end, so the 1st socket left connected to the dead socket with a
message from it.
II) Run the state
This is when test actually creates a process that does the syscalls
required to get into the generated state (and hopefully gets into it).
III) Check C/R of the state
This is the trickiest part when it comes to the R step -- it's not
clear how to validate that the state restored is correct. But if only
trying to dump the state -- it's just calling criu dump. As images dir
the state string description is used.
One may choose only to generate the states with --gen option. One may
choose only to run the states with --run option. The latter is useful
to verify that the states generator is actually producing valid
states. If no options given, the state is also dump-ed (restore is to
come later).
For now the usage experience is like this:
- Going --depth 10 --gen (i.e. just generating all possibles states
that are acheivable with 10 syscalls) produces 44 unique states for
0.01 seconds. The generated result covers some static tests we have
in zdtm :) More generation stats is like this:
--depth 15 : 1.1 sec / 72 states
--depth 18 : 13.2 sec / 89 states
--depth 20 : 1 m 8 sec / 101 state
- Running and trying with criu is checked with --depth 9. Criu fails
to dump the state SA-CX-MX_SBL (shown above) with the error
Error (criu/sk-queue.c:151): recvmsg fail: error: Connection reset by peer
Nearest plans:
1. Add generators for on-disk sockets names (now oly abstract).
Here an interesting case is when names overlap and one socket gets
a name of another, but isn't accessible by it
2. Add datagram sockets.
Here it'd be fun to look at how many-to-one connections are
generated and checked.
3. Add socketpair()-s.
Farther plans:
1. Cut the tree better to allow for deeper tree scan.
2. Add restore.
3. Add SCM-s
4. Have the exhaustive testing for other resources.
Changes since v1:
* Added DGRAM sockets :)
Dgram sockets are trickier that STREAM, as they can reconnect from
one peer to another. Thus just limiting the tree depth results in
wierd states when socket just changes peer. In the v1 of this patch
new sockets were added to the state only when old ones reported that
there's nothing that can be done with them. This limited the amount
of stupid branches, but this strategy doesn't work with dgram due to
reconnect. Due to this, change #2:
* Added the --sockets NR option to limit the amount of sockets.
This allowed to throw new sockets into the state on each step, which
made a lot of interesting states for DGRAM ones.
* Added the 'restore' stage and checks after it.
After the process is restore the script performs as much checks as
possible having the expected state description in memory. The checks
verify that the values below get from real sockets match the
expectations in generated state:
- socket itself
- name
- listen state
- pending connections
- messages in queue (sender is not checked)
- connectivity
The latter is checked last, after all queues should be empty, by
sending control messages with socket.recv() method.
* Added --keep option to run all tests even if one of them fails.
And print nice summary at the end.
So far the test found several issues:
- Dump doesn't work for half-closed connection with unread messages
- Pending half-closed connection is not restored
- Socket name is not restored
- Message is not restored
New TODO:
- Check listen state is still possible to accept connections (?)
- Add socketpair()s
- Add on-disk names
- Add SCM-s
- Exhaustive script for other resources
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Andrew reported that previously he been able to c/r even
on the machine with xsavec enabled, so allow to process
for now.
P.S.I'm investigating the problem and to not block testing
process lets permit passing with xsaves bit present.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For easier understanding what is failed.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With new cpu-cap='op=noxsaves' mode on x86 we should use
compel's instance of rt info since only it carries
features masked.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently even if kernel supports compact xsave frame a user
can disable it by passing noxsaves argument as a boot option.
Thus cpuid instruction will report its presence but in real
it gonna be masked from kernel pov. Lets do the same and
allow a user to mask it via --cpu-cap=noxsaves option
(valid for x86 only).
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Will need them to mask some of the features from
command line options.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't have yet support of compacted xsave frames so report
error on cpu-check, checkpoint, restore actions. Basically
it is done in cpu_init routine which is called in the sites
we're interested in.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Tracking cpuid features is easier when sync'ed with kernel
source code. Note though that while in kernel feature bits
are not part of ABI, we're saving bits into an image so
as result make sure they are posted in proper place together
with keeping in mind the backward compatibility issue.
Here we also start using v2 of cpuinfo image with more
feature bits.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
A set of images from criu dump can be used as a previous point, when we
are doing snapshots. In this case, each point contains a full set of
images.
https://github.com/checkpoint-restore/criu/issues/479
v2: return -1 if invertory_save_uptime failed
Cc: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The travis build for s390x started to fail with:
Failed to fetch http://security.debian.org/debian-security/dists/jessie/updates/InRelease Unable to find expected entry 'main/binary-s390x/Packages' in Release file (Wrong sources.list entry or malformed file)
This changes the repository definition just like it is done for ppc64le.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Send pre-dump notify to 36
Traceback (most recent call last):
File "zdtm.py", line 2161, in <module>
do_run_test(tinfo[0], tinfo[1], tinfo[2], tinfo[3])
File "zdtm.py", line 1549, in do_run_test
cr(cr_api, t, opts)
File "zdtm.py", line 1264, in cr
test.pre_dump_notify()
File "zdtm.py", line 490, in pre_dump_notify
fdin.write(struct.pack("i", 0))
TypeError: write() argument 1 must be unicode, not str
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The idea of the test is:
1) mmap separate page and put variable there, so that other usage does
not dirty these region. Initialize the variable with VALUE_A.
2) fork a child with special pid == CHILD_NS_PID. Only if it is a first
child overwrite the variable with VALUE_B.
3) wait for the end of the next predump or end of restore with
test_wait_pre_dump_ack/test_wait_pre_dump pair and kill our child.
Note: The memory region is "clean" in parent.
4) goto (2) unles end of cr is reported by test_waitpre
So on first iteration child with pid CHILD_NS_PID was dumped with
VALUE_B, on all other iterations and on final dump other child with the
same pid exists but with VALUE_A. But on all iterations after the first
one we have these memory region "clean". So criu before the fix would
have restored the VALUE_B taking it from first child's image, but should
restore VALUE_A.
Note: Child in its turn waits termination and performs a check that variable
value doesn't change after c/r.
We should run the test with at least one predump to trigger the problem:
[root@snorch criu]# ./test/zdtm.py run --pre 1 -k always -t zdtm/transition/pid_reuse
Checking feature ns_pid
Checking feature ns_get_userns
Checking feature ns_get_parent
=== Run 1/1 ================ zdtm/transition/pid_reuse
===================== Run zdtm/transition/pid_reuse in ns ======================
DEP pid_reuse.d
CC pid_reuse.o
LINK pid_reuse
Start test
Test is SUID
./pid_reuse --pidfile=pid_reuse.pid --outfile=pid_reuse.out
Run criu pre-dump
Send the 10 signal to 52
Run criu dump
Run criu restore
Send the 15 signal to 73
Wait for zdtm/transition/pid_reuse(73) to die for 0.100000
Test output: ================================
14:47:57.717: 11235: ERR: pid_reuse.c:76: Wrong value in a variable after restore
14:47:57.717: 4: FAIL: pid_reuse.c:110: Task 11235 exited with wrong code 1 (errno = 11 (Resource temporarily unavailable))
<<< ================================
https://jira.sw.ru/browse/PSBM-67502
v3: simplify waitpid's status check
v9: switch to test_wait_pre_dump(_ack)
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Commit 37e4c7bfc264 fixed arm, ppc, x86 (32bit),
while it made wrong definition of x86_64. Fix that.
Also, add commentary to raw fork() implementation.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The criu_status_in is not always used and it may be -1 when the signal
handler closes it. With lazy-pages we hit a corner case which clobbers the
errno value. This happens when we resume the process inside glibc syscall
wrapper and get the signal before the page containing errno is copied. In
this case, signal handler is invoked before the syscall return value is
written to errno and the actual value of errno seen by the process becomes
-EBADF because of close(-1) in the signal handler.
Let's ensure that close() in signal handler does not fail to make Jenkins
happier while the proper solution for the lazy-pages issue is found.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The kerndat_init() is now called before the jump to action handler. This
allows us to directly use kdat without calling to the corresponding
kerndat_*() methods.
✓ travis-ci: success for lazy-pages: update checks for availability of userfaultfd (rev3)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
On fedora rawhide seccomp_metadata for some
reason is not defined (while in kernel it introduced
together with PTRACE_SECCOMP_GET_METADATA). So
lets do a trick for a while -- define own alias.
Once system headers get settled down we might find
more suitable solution. Because it's a part of kernel
API we're on the safe side.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After CR_STATE_RESTORE_SIGCHLD stage triggered we are
not allowed to exit, just yield the BUG instead.
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Credential commitment affects dumpable and pdeath signals
so we have to move their restore after the restore_creds,
just like we have in __export_restore_task (ie for
group leader).
https://jira.sw.ru/browse/PSBM-84198
Acked-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Looking up for pid in nesting pidns supposed to be done
for non group leaders only, thus __export_restore_thread
do this check on its own and we don't have to make
a similar lookup especially on group leader where
pids in args never were valid.
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Andrew proposed the test which actually triggered the issue
in current seccomp series, put it into a regular basis.
Suggested-by: Andrey Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When considering if we to call PTRACE_O_SUSPEND_SECCOMP
on the tid we should take into account if there at least
one thread which has seccomp mode enabled, otherwise
we might miss filter suspension and restore procedure
might break due to own criu syscall get filtered out.
Same time we should move seccomp restore for threads
to take place after CR_STATE_RESTORE_SIGCHLD state
so that main criu code will attach to threads and
setup seccomp suspension flag before we start
restoring the filters.
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To checkpoint per-thread seccomp filters we need
a significant rework of a dumping code. The general
idea is the following:
- Each thread is tracked by its tid inside global
seccomp rbtree thus we can easily add entries
there or lookup on demand.
- When we collect threads into pstree entries we fetch
its seccomp mode from procfs parsing routine and allocate
a new entry inside rbtree to remember the seccomp mode.
Note at this moment we're not dumping real filters yet
(because filter data image is a single one for all consumers)
- Once all tids are collected and our tree is complete we call for
seccomp_collect_dump_filters helper which walks every pstree entry
and iterate over each tid inside thread group calling
seccomp_dump_thread, which in turn uses ptrace engine to fetch
filters and keep this data in memory.
To optimize data usage we figure out if we can use TSYNC flag
on restore calling try_use_tsync helper: for TSYNC flag kernel
automatically propagate filter to all threads, thus we need to
compare all filters inside thread group for identity since there
is no other way to figure out if user passed TSYNC flag when
been creating filters.
- Finally dump_seccomp_filters is called which does real write
of seccomp filter data into an image file.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
At now we pretend that all threads are sharing seccomp chains
and at checkpoint moment we test seccomp modes to make sure
if this assumption is valid refusing to dump otherwise.
Still the kernel tacks seccomp filter chains per each thread
and now we've faced applications (such as java) where per-thread
chains are actively used. Thus we need to bring support of handling
filters via per-thread basis.
In this a bit intrusive patch the restore engine is lifted up
to treat each thread separately. Here what is done:
- Image core file is modified to keep seccomp filters
inside thread_core_entry. For backward compatibility
former seccomp_mode and seccomp_filter members in
task_core_entry are renamed to have old_ prefix and
on restore we test if we're dealing with old images.
Since per-thread dump is not yet implemeneted the
dumping procedure continue operating with old_ members.
- In pie restorer code memory containing filters are addressed
from inside thread_restore_args structure which now
contains seccomp mode itself and chain attributes
(number of filters and etc).
Reading of per-thread data is done in seccomp_prepare_threads
helper -- we take one pstree_item and walks over every thread
inside to allocate pie memory and pin data there.
Because of PIE specific, before jumping into pie code
we have to relocate this memory into new place and
for this seccomp_rst_reloc is served.
In restorer itself we check if thread_restore_args provides
us enabled seccomp mode (strict or filter passed) and call
for restore_seccomp_filter if needed.
- To unify names we start using seccomp_ prefix for all related
stuff involved into this change (prepare_seccomp_filters renamed
to seccomp_read_image because it only reads image and nothing
more, image handler is renamed to seccomp_img_entry instead
of too short 'se'.
With this change we're now allowed to start collecting and
dumping seccomp filters per each thread, which will be
done in next patch.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Note that there is no real usage of this flag on restore,
we simply save it in image and will make a real use
later.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This header is main place for all seccomp related
structures so move seccomp_info here. This will
allow to minimize changes area when need to update
definitions and such.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We will use it to figure out if filter log target is used.
Metadata associated with seccomp filter is relatively new
feature which allows userspace to get and set it back.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If pre-dump-notify flag is set, zdtm sends a notify to the test after
pre-dump was finished and waits for the test to send back a reply that
test did all it's work and now is ready for a next pre-dump/dump.
How it can be used:
while (!test_wait_pre_dump()) {
/* Do something after predump */
test_wait_pre_dump_ack();
}
/* Do something after restore */
Internally we open two pipes for the test one for receiving notify (with
two open ends) and one for replying to it (only write end open). Fds of
pipes are dupped to predefined numbers and zdtm opens these fds through
/proc/<test-pid>/fd/{100,101} and communicates with the test.
v9: switch to two way interface to remove race then operation we try to
run after predump may be yet unfinished at the time of next dump.
Suggested-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We have a problem when a pid is reused between consequent dumps we can't
understand if pagemap and pages from images of parent dump are invalid
to restore these pid already. That can lead even to wrong memory
restored for these pid, see the test in last patch.
So these is a try do separate processes with (likely) invalid previous
memory dump from processes with 100% valid previous dump.
For that we use the value of /proc/<pid>/stat's start_time and also the
timestamp of each (pre)dump. If the start time is strictly less than the
timestamp, that means that the pagemap for these pid from previous dump
is valid - was done for exactly the same process.
Creation time is in centiseconds by default so if predump is really fast
(<1csec) we can have false negative decisions for some processes, but in
case of long running processes we are fine.
https://jira.sw.ru/browse/PSBM-67502
v2: remove __maybe_unused for get_parent_stats; fix get_parent_stats to
have static typing; print warning only if unsure; check has_dump_uptime
v3: read parent stats from image only once; reuse stat from previous
parse_pid_stat call on dump
v4: move code to function; use unsigned long long for ticks; put
proc_pid_stat on mem_dump_ctl; print warning on all pid-reuse cases
v5: free parent's stats entry properly, pass it in arguments to
(pre_)dump_one_task
v6: free parent's stats in error path too
v7: zero init parent_se
v8: improve error message
v9: switch to inventory image from stats, if pid-reuse fails - fail
current dump
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
will be used in the next patch
https://jira.sw.ru/browse/PSBM-67502
note: actually we need only one value from inventory entry but I still
prefer general helper as we still need to read and allocate memory
for the whole structure
v2: fix get_parent_stats to have static typing
v3: simplify get_parent_stats to return a StatsEntry pointer instead of
doing it through arguments
v8: replace errors with warnings, we should whatch on them only if we
have corresponding error in detect_pid_reuse else they are fine
v9: change stats to inventory image
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We want to use a simple fact: If we have an alive process in a pstree we
want to dump, and a starttime of that process is less than pre-dump's
timestamp (taken while all processes were freezed), then these exact
process existed (100% sure) at the time of these pre-dump and the
process' memory was dumped in images.
So save inventory image on pre-dump and put there an uptime.
https://jira.sw.ru/browse/PSBM-67502
v9: improve comment, put uptime to ivnentory image as 1) where is no
stats in parent images directory if --work-dir option is set to
something different then images directory, 2) stats-dump is not an image
and it is a bad practice to put there data required for restoring.
v10:s/u_int64_t/uint64_t/
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
will be used in the next patch
https://jira.sw.ru/browse/PSBM-67502
note: man for /proc/uptime says that uptime is in seconds and for now
the format is "seconds.centiseconds", where ecentiseconds is 2 digits
note: now uptime is in csec but I prefer saving it in usec, that allows
us to be reuse these image field when/if we have more accurate value.
v8: add length specifier to parse only centiseconds
v9: put uptime to u_int64_t directly, define CSEC_PER_SEC
v10: switch to uint64_t from u_int64_t, comment about usec in image
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This makes it possible to have the pageserver communication go over anonymous
unix sockets, e.g. created by socketpair().
Such setup makes it easier to secure pageserver connection by wrapping
it in an encrypted tunnel. It also helps prevent attacks where
a malicious process connects to page server and injects its own
stream of pages to either fool criu into restoring wrong pages or
to DoS the pageserver by having it exhaust local storage by writing
large .img files.
Signed-off-by: Pawel Stradomski <pstradomski@google.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case if master peer of veth device is laying inside
node root net-ns we should not request device index
but rather allow the kernel to number it automatically.
When there is separate net-ns for master peer it should
be safe to request an index though.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
service_binary is either set to a const char * (CR_DEFAULT_SERVICE_BIN)
or to a user provided char *, but there is no reason to give a char *.
Users of such function will most likely provide a const char *,
that will generate a warning.
Thus, we add the const qualifier to better represent the usage of
service_binary, and avoid such warnings.
Signed-off-by: Ronny Chevalier <ronny.chevalier@hp.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The script checks if $NSENTER is executable and sets $NS_ENTER if not.
This seems to be a typo (once with '_' and once without).
Untested and not reproducible. It just looks wrong.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We have a problem after commit 212e4c771a ("test: make zdtm.py
python2/python3 compatible") when running tests on python2:
https://ci.openvz.org/job/CRIU/job/CRIU-virtuozzo/job/criu-dev/3804/console
Traceback (most recent call last):
File "./test/zdtm.py", line 2249, in <module>
opts['action'](opts)
File "./test/zdtm.py", line 2001, in run_tests
launcher.run_test(t, tdesc, run_flavs)
File "./test/zdtm.py", line 1680, in run_test
self.wait()
File "./test/zdtm.py", line 1737, in wait
self.__wait_one(0)
File "./test/zdtm.py", line 1725, in __wait_one
print(open(sub['log']).read())
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2018' in
position 258: ordinal not in range(128)
print does not like "‘" symbol in zdtm_static_cgroup04.log:
...
rmdir: failed to remove ‘cgclean.sKFHLm/zdtmtst/special_prop_check’: No
such file or directory
Small reproducer:
[snorch@snorch ~]$ cat test_ascii.py
from __future__ import absolute_import, division, print_function, unicode_literals
from builtins import (str, open, range, zip, int, input)
f = open('./zdtm_static_cgroup04.log')
s = f.read()
print(s)
[snorch@snorch ~]$ python test_ascii.py | grep ""
Traceback (most recent call last):
File "test_ascii.py", line 6, in <module>
print(s)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2018' in
position 258: ordinal not in range(128)
So just ignore these quote symbol when printing logs.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To test the case where sockets are removed
together with directory they are living in.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unix sockets may be connected via deleted socket name,
moreover the name may be reused (ie same sun_addr but
different inodes).
To be able to handle them we do a few tricks:
- when collecting sockets we figure out if "deleted"
mark is present on the socket and if such we order
this sockets creation and deletion with mutex, together
with adding missing directories, and save this descriptors
in fdstore if there are peers connected to
- on restore we connect via procfs/fd/X as suggested by
Andrew Vagin
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For debug sake, to unify with helpers tools such
as ss, stat and etc.
Requested-by: Andrey Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We gonna use it to detele not only stale
sockets but ghost sockets as well.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Most of them already in hex form, lets do the same for the rest.
Also incoming connections are identified by inode number
so use hex for them as well for consistency.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
While trying to resurrect the test cases in test/other/rpc one test case
was checking for returned errors during restore failures. The process
was dumping itself and while the process kept on running it tried to
restore from that checkpoint. That should fail as the PID is in use of
the process doing the test. CRIU, however, killed the test process
during restore failure.
This is the fix as proposed by Andrei Vagin on the CRIU mailing list.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To be close to the kernel code.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
zdtm/static/maps06 failed on systems with different page-size than 4096.
This changes maps06 to use sysconf(_SC_PAGESIZE) instead.
Signed-off-by: Adrian Reber <areber@redhat.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We operate by long variables in out bit arithmetics, so our constants
should be marked as long too.
Cc: Adrian Reber <areber@redhat.com>
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Tested-by: Adrian Reber <areber@redhat.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We alwasy exclude vsyscall vma-s for x32 tests, but
this part was broken by python3 patches.
1: Old maps lost: set([])
1: New maps appeared: set([u"ffffffffff600000-ffffffffff601000 [u'r-xp']"])
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Improve code readability and take into account that even if
uffdio_{copy,zeropage} has failed, some pages had been updated.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
is_any_service_fd didn't check for service file descriptor
being marked in sfd_map in result we may end up leaving
some garbage file obtained from the program executing
criu.
[root@sqvm0910 criu-stable.git]# ll /proc/354877/fd
lr-x------ 1 root root 64 May 16 19:03 114 -> /
lr-x------ 1 root root 64 May 16 19:03 115 -> /
l--------- 1 root root 64 May 16 19:03 117 -> /18311 (deleted)
lr-x------ 1 root root 64 May 16 19:03 119 -> /vzt/del/vzctl-rm-me.X1JH4vI (deleted)
We are to test if the file descriptor was indeed installed
explicitly.
https://jira.sw.ru/browse/PSBM-83892
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I am regularly running zdtm.py after updating the CRIU rpm to test if
the new rpm still works. Until know I usually did:
-criu_bin = "../criu/criu"
-crit_bin = "../crit/crit"
+criu_bin = "/usr/sbin/criu"
+crit_bin = "/usr/bin/crit"
This commit adds two arguments to zdtm.py:
--criu-bin CRIU_BIN Path to criu binary
--crit-bin CRIT_BIN Path to crit binary
It still defaults to the old values from above, but can now easily be
changed to the CRIU binary provided by the packaging system.
This change was more complicated than expected which is probably related
to the fact that zdtm restarts itself in namespaces.
v2:
- rebase
v3:
- fix errors reported by 'make lint'
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
check_tun_netns_cr() should return 0 on CONFIG_TUN=n kernels.
That is, when we fail to open tun device.
Fixes: #496
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
test/dump/zdtm/static/msgque/43/1/ipcns-msg-12.img decode fails: object of type 'NoneType' has no len()
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Running the test suite on aarch64 showed two tests failing (static/fd
and transition/maps0007). Debugging showed that the
atomic_{sub,add}_return() functions did not return the value but the
lower 32bit of the address of that value.
Simply dereferencing the input solves the two mentioned test cases.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Syscalls do return negative value in case of an error.
But errno contains the error code itself.
Add uint32_t to sys_futex() definition.
sizeof(unsigned int) might be not 4 bytes.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Send pre-dump notify to 36
Traceback (most recent call last):
File "zdtm.py", line 2161, in <module>
do_run_test(tinfo[0], tinfo[1], tinfo[2], tinfo[3])
File "zdtm.py", line 1549, in do_run_test
cr(cr_api, t, opts)
File "zdtm.py", line 1264, in cr
test.pre_dump_notify()
File "zdtm.py", line 490, in pre_dump_notify
fdin.write(struct.pack("i", 0))
TypeError: write() argument 1 must be unicode, not str
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Here is an example of ldd output:
/musl # ldd /usr/lib/libxtables.so.12
ldd (0x7fae8e06c000)
libc.musl-x86_64.so.1 => ldd (0x7fae8e06c000)
We need to skip the "ldd (0x7fae8e06c000)" line.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't tune tracers, so we don't expect to get anything.
In docker containers, debugfs isn't mounted and this command failed.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
fprintf in Alpine Linux calls writev, which is prohibited in the
SECCOMP_MODE_STRICT mode.
===================== Run zdtm/static/seccomp_strict in h ======================
Start test
Test is SUID
./seccomp_strict --pidfile=seccomp_strict.pid --outfile=seccomp_strict.out
make: *** [Makefile:385: seccomp_strict.pid] Error 1
Test zdtm/static/seccomp_strict FAIL at start: [Errno 2] No such file or directory: 'zdtm/static/seccomp_strict.pid'
Test output: ================================
22:45:24.661: 38: ERR: seccomp_strict.c:97: read (errno = 2 (No such file or directory))
22:45:24.662: 37: ERR: test.c:315: Test exited unexpectedly with code 1
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise one library will be imported twice by two different names: py
and pycriu, because pycriu is used in the library.
https://github.com/checkpoint-restore/criu/issues/495
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case if dump_namespaces failed we may have
ret shadowed and erroneously report checkpoint
success.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For python2/python3 compatibility install additional (python2-future)
and different (python2-ipaddress) packages during test.
Also switch Fedora tests to explicitly install versioned python packages
(python2-* instead of python-*).
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As python3 imports are working a bit differently the structure of the
imported files needs to change. Instead of having symlinks to criu.py
and rpc_pb2.py which does not match the import structure just create
symlink to ../lib/py (like crit) to make zdtm usable again with the
python3 compatibility.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With this last commit of the crit with python3 series it is possible to
either use python2 or python3 with CRIU.
Now the basic build system functionality (make and make install) are
python2/python3 aware. zdtm.py and criu-coredump are still python2, but
as they are not part of 'make install' those parts have not yet been
ported from python2 to python3.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This prepares CRIT for python2/python3 compatibility by auto-detecting
the installed python version. python2 is detected first and then the
variable PYTHON is set.
By setting the variable PYTHON to python2/python3 the user can override
the auto-detection.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This helper must init every member of a structure,
not some part of it. Beautify code as well.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise there is an imbalance in logs with number of
"Reverted working dir" message
| (00.018604) 36: unix: Connected 0x11ceff -> 0x11cf00 (0x11cf00) flags 0
| (00.018644) 36: unix: Reverted working dir
| (00.018652) 36: unix: Connected 0x11cefd -> 0x11cefe (0x11cefe) flags 0
| (00.018665) 36: unix: Reverted working dir
| (00.018688) 36: unix: Reverted working dir
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To unify style of pointers fetching from memory slab.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For readability sake. And use standart uint8_t types.
Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is one of our target platforms.
Cc: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On ppc64/aarch64 Linux can be set to use Large pages, so the PAGE_SIZE
isn't build-time constant anymore. Define it through _SC_PAGESIZE.
There are different sizes for a page on ppc64:
: #if defined(CONFIG_PPC_256K_PAGES)
: #define PAGE_SHIFT 18
: #elif defined(CONFIG_PPC_64K_PAGES)
: #define PAGE_SHIFT 16
: #elif defined(CONFIG_PPC_16K_PAGES)
: #define PAGE_SHIFT 14
: #else
: #define PAGE_SHIFT 12
: #endif
And on aarch64 there are default sizes and possibly someone can set his
own PAGE_SHIFT:
: config ARM64_PAGE_SHIFT
: int
: default 16 if ARM64_64K_PAGES
: default 14 if ARM64_16K_PAGES
: default 12
On the downside - each time we need PAGE_SIZE, we're doing libc
function call on aarch64/ppc64.
Fixes: #415
Tested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
PAGE_SIZE will be a variable value on platforms where it can be
different due to large pages.
And looks like (c) there is no reason for BUF_SIZE == PAGE_SIZE,
so let's keep it as it was, rather than complicating it with dynamic
allocation for the buffer.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The same value, but as PAGE_SIZE can be different for the same
platform - it's no more static value.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Personality value is printed in kernel like this:
static int proc_pid_personality(/* .. */)
{
int err = lock_trace(task);
if (!err) {
seq_printf(m, "%08x\n", task->personality);
unlock_trace(task);
}
return err;
}
So, we don't need a whole page to read the value.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For architectures like aarch64/ppc64 it's needed to propagate the size
of page inside PIEs. For the parasite page size will be defined during
seizing, and for restorer during early initialization.
Afterward we can use PAGE_SIZE in PIEs like we did before.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The macro is used only in aio_estimate_nr_reqs():
unsigned int k_max_reqs = NR_IOEVENTS_IN_NPAGES(size/PAGE_SIZE);
Which compiler may evaluate as (((PAGE_SIZE*size)/PAGE_SIZE) - ...)
It works as long as PAGE_SIZE is long.
The patches set converts PAGE_SIZE to use sysconf() returning
(unsigned), non-long type and making the aio macro overflowing.
I do not see any value making PAGE_SIZE (unsigned long) typed.
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's actually number of bytes spliced, not pages.
And I bet (unsigned long) suits the purpose more than (int).
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's unused since commit fd3f33f5d2 ("headers: image.h -- Drop unused
entries"), so let's remove it completely.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise, tests dependencies are not considered for build.
Add an error in Makefile.inc so this won't happen again.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This reverts commit dcafa78b96.
I've found that we already include deps in Makefile.inc,
was to fast on the first attempt and overlooked this.
(the include just doesn't work like it should yet..)
The origin patch may be just dropped before preparing master's merge.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 190174 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
6. negative_returns: fd is passed to a parameter that cannot be negative.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
>>> CID 190177: Integer handling issues (NEGATIVE_RETURNS)
>>> rpc_sk is passed to a parameter that cannot be negative.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 84654 (#1 of 1): Resource leak (RESOURCE_LEAK)
6. leaked_handle: Handle variable fd going out of scope leaks the handle.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The purpose of the num_children field in 'struct lazy_pages_info' was to
prevent closing the page-read while there are still active processes that
share it. It did work for the case when handling of the child processes
finished before the parent process. However, if the parent lpi is closed
first, we've got a dangling pointer at lpi->parent.
The obvious solution is to use simple reference counting.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is possible that notification about restore finish arrives at the same
time with a fork event. In such case we return to epoll_run_rfds without
resetting the poll_timeout and then we'll keep polling for events
indefinitely. To avoid this, we reset the poll_timeout to 0 as soon as we
know that restore is finished.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The only use for the userfault file descriptor after the process exited is
for debug logs. Using negative value instead of 0 makes logs more readable.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Although they are the same, xfree() looks more consistent with other code
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are a lot of lines, which are longer than 79:
(04.331172)pie: 1: Error (criu/pie/restorer.c:460): seccomp: Unexpected tid ->
(04.331172)pie: 1: 1 != 1
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
kerndat_try_load_cache() fills kdat from /run/criu.kdat,
so it will contain some trash, if criu.kdat isn't compatible with the
current version of criu.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is test that triggers a bug with ghost files, that was resolved in
patch "Don't fail if ghost file has no parent dirs".
Signed-off-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This test creates a pty pair, creates a test process and sets a slave
pty as control terminal for it.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Here is one of often mistakes:
int funcX()
{
int ret;
ret = funcA()
if (ret < 0)
goto err;
if (smth)
goto err; // return 0 !!!!
err:
return ret;
}
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There is no reasons we need this cleanup code in generic
restore_one_task(), so let's move it for better readability.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When dumping a process with a large number of open files,
dump_task_files_seized() processes the fds in batches. If
dump_one_file() results in an error, processing of the current batch is
stopped but the next batch (if any) will still be fetched and the error
value is overwritten. The result is a corrupt dump image (the fdinfo
file is missing a bunch of fds) which results in restore failure.
Also close all received fds after an error (previously the skipped ones
were left open).
Signed-off-by: Andy Tucker <agtucker@google.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
log_init() opens a log file. We want to have criu and kernel versions in
each log file, so it looks reasonable to print them from log_init().
Without this patch, versions are not printed, if criu is called in the
swrk mode.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We have three code paths, where we call log_set_loglevel() and in all
these places, we need to initialize libraries logging engines, so it is
better to do this from one function. For example, currently we forgot to
initialize soccr logging for criu swrk.
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
iptables creates /run/xtables.lock file and
we want to have it per-test.
(00.332159) 1: Running iptables-restore -w for iptables-restore -w
Fatal: can't open lock file /run/xtables.lock: Permission denied
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Starting with iptables 1.6.2, we have to use the --wait option,
but it doesn't work properly with userns, because in this case,
we don't have enough rights to open /run/xtables.lock.
(00.174703) 1: Running iptables-restore -w for iptables-restore -w Fatal: can't open lock file /run/xtables.lock: Permission denied
(00.192058) 1: Error (criu/util.c:842): exited, status=4
(00.192080) 1: Error (criu/net.c:1738): iptables-restore -w failed
(00.192088) 1: Error (criu/net.c:2389): Can't create net_ns
(00.192131) 1: Error (criu/util.c:1567): Can't wait or bad status: errno=0, status=65280
This patch workarounds this problem by mounting tmpfs into /run.
Net namespaces are restored in a separate process, so we can create a
new mount namespace and create new mounts.
https://github.com/checkpoint-restore/criu/issues/469
Cc: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
iptables 1.6.2 fails without /run, because it tries to create
the /run/xtables.lock file
Test output: ================================
Fatal: can't open lock file /run/xtables.lock: No such file or directory
23:29:06.098: 4: ERR: netns-nf.c:21: Can't set input rule (errno = 2 (No such file or directory))
23:29:06.098: 3: ERR: test.c:315: Test exited unexpectedly with code 255
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This function is an analogue to vsprintf(), and is used in very much the
same way. The caller expects the modified string pointer to be pointing to
a null-terminated string.
Signed-off-by: Joel Nider <joeln@il.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In file included from s390x_gs_threads.c:10:0:
../lib/lock.h: In function 'mutex_lock':
../lib/lock.h:148:4: error: implicit declaration of function 'pr_perror' [-Werror=implicit-function-declaration]
pr_perror("futex");
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We shouldn't set MAKEFLAGS by the following reasons:
1. User may want to specify some make parameter (e.g., `-d` for debug)
2. We lose parallel build. No `-j` is passed to submake and it looks
like, gnu/make will not deal with parallel recursive make if
$(MAKEFLAGS) is unset back.
Easy to verify: Add `sleep 3` to build rule in Makefile.inc and
you'll find only one sleep process at a time. After the patch
if you specify say `-j5` to make - you'll have 5 sleep processes.
Reverts: commit e9beed7bb3 ("build: zdtm -- Add implicit rules into
zdtm building").
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's drop usage of COMPILE.c, OUTPUT_OPTION.
It will allow run submake with -R.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
$(MAKEFLAGS) already contains -r -R and --no-print-directory: those
flags are being added in include.mk.. which is included two lines above.
There is no comment and I see no big sense in erasing $(MAKEFLAGS),
rather than adding those flags. So I considered this as a typo.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Service descriptros can be moved in a child process.
v2: handle errors of install_service_fd() properly
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Include deps files to recompile tests when dependency has changed.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
man 2 futex:
In the event of an error (and assuming that futex() was invoked via
syscall(2)), all operations return -1 and set errno to indicate the
cause of the error.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Though LOG_FD_OFF < IMG_FD_OFF, get_service_fd(LOG_FD_OFF) is > than
get_service_fd(IMG_FD_OFF), see __get_service_fd, so the check here
should be twisted. Also add bug_on to track possible __get_service_fd
change which can break these check again.
We have a problem when USERNSD_SK replaces LOG_FD_OFF, latter when
writing to log, instead we actually send crazy commands to usernsd,
which fails to handle them and BUGs or crashes.
https://jira.sw.ru/browse/PSBM-83472
Also we had similar problem when __userns_call receives bad repsonse,
likely it has the same background:
https://api.travis-ci.org/v3/job/352164661/log.txt
fixes commit 129bb14611 ("files: Prepare clone_service_fd() for
overlaping ranges.")
v2: move BUG_ON to main() to check it only once, use min+1 and max-1
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Acked-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unnamed temporary files are restored as ghost files.
If O_TMPFILE is set for the open() syscall, the pathname argument
specifies a directory, but criu gives a path to a ghost file.
(00.107450) 36: Error (criu/files-reg.c:1757): Can't open file tmp/#42274874 on restore: Not a directory
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
man 2 open:
...
O_TMPFILE (since Linux 3.11)
Create an unnamed temporary file. The pathname argument speci‐ fies a
directory; an unnamed inode will be created in that directory's
filesystem. Anything written to the resulting file will be lost when
the last file descriptor is closed, unless the file is given a name.
...
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Sometimes we see errors like this:
criu/cr-restore.gcda:Merge mismatch for function 106
It proabably means that this gcda file was corrupted. According to the
gcc man page, the -fprofile-update=atomic should fix this problem.
v2: this options appered in gcc7, so we need to install it.
Reported-by: Mr Travis CI
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Make sure we handle various corner cases:
* we received less pages than requested
* the request was capped because of unmap/remap etc
* the process has exited underneath us
Currently we are freeing the request once we've found the address to use
with uffd_copy(). Instead, let's keep the request object around, use it to
properly calculate number of pages we pass to uffd_copy() and then re-add
tailing range (if any) to the IOVs list.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of merging unfinished requests with child's IOVs we queued them
into parent's IOV list. Fix it.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Commit 9cb20327aa ("return to epoll_wait after completing forks") was only
half way there. Adding the other half.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is possible that when pages request from the remove source arrive, part
of the memory range covered by the request would be already gone because of
madvise(MADV_DONTNEED), mremap() etc.
Ensure we are not trying to uffd_copy more than we are allowed.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If we get fork() event just before transferring last IOV of the parent
process, continuing to background fetch after completing fork event
handling will cause lazy-pages daemon to exit and nothing will monitor the
child process memory.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since the memory mapping is now split between ->iovs and ->reqs lists, any
update to memory layout should take into account both lists.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of recalculating required for lazy_pages_info->buf when copying
IOVs at fork() time, keep the size of the buffer in the lazy_pages_info
struct.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we return from epoll_run_rfds with positive return value it means that
event handling loop was interrupted because the event should be handled
outside of that loop. Is always the case with UFFD_EVENT_FORK.
It may happen that the event occurred after we've completed the memory
transfer and we are on the way to successful return from the
handle_requests() function, but instead of returning 0 we will return the
positive value we've got from epoll_run_rfds.
Explicitly assigning return value of complete_forks() fixes this issue.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With userfaultfd we cannot reliably service process_vm_readv calls. The
maps007 test that uses these calls passed previously by sheer luck.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In the current model we haven't started the background page transfer until
POLL_TIMEOUT time has elapsed since the last uffd or socket event. If the
restored process will do memory access one in (POLL_TIMEOUT - eplsilon) the
filling of its memory can take ages.
This patch changes them model in the following way:
* poll for the events indefinitely until the restore is complete
* the restore completion event causes reset of the poll timeout to zero and
* starts the background transfers
* after each transfer we return to check if there are any uffd events to
handle
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently, once we get to transfer pages in the "background", we try to
fetch the entire IOV at once. For large IOVs this may impact #PF latency
for the #PF events occurred during the transfer.
Let's add a simple heuristic for controlling size of the background
transfers. Initially, the transfer will be limited to some default value.
Every time we transfer a chunk we increase the transfer size until it
reaches a pre-defined maximal size. A page fault event resets the
background transfer size to its initial value.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The complete_forks function presumes that it always has a work to do
because we assume that fork event is the only case when we drop out of
epoll_run_rfds with positive return value.
Teach complete_forks to bail out when there is no pending forks to process
to allow exiting epoll_run_rfds for different reasons.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
First check if there are pages we need to transfer and only afterwards
check if there are outstanding requests. Also, instead checking 'bool
remaining' to see if there is more work to do we can simply check if all
the lpi's have been already serviced.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The intention is to use this function for transferring all the pages that
didn't cause a #PF.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The function anyway pick the next page range to transfer it's just doing it
in very simple FIFO manner.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We already have a queue for the requested memory ranges which contains
'lp_req' objects. These objects hold the same information as the lazy_iov:
start address of the range, end address and the address that the range had
at the dump time.
Rather than keep this information twice and use double bookkeeping, we can
extract the requested range from lpi->iovs and move it to lpi->reqs.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of relying on length of various lists add a boolean variable to
lazy_pages_info to make it clean when the process has exited
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently zdtm doesn't detect when restore failed, if it is executed
with strace. With this patch, fake-restore.sh creates a test file, and
zdtm is able to distinguish when restore failed.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The get() method requires a key and now we are using an index. That
will never work correctly as it is now.
Acked-by: Adrian Reber <adrian@lisas.de>
Reported-by: Adrian Reber <adrian@lisas.de>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we restore all sockets in the root mount namespace, because we
were not able to get any information about a mount point where a socket
is bound. It is obviously incorrect in some cases.
In 4.10 kernel, we added the SIOCUNIXFILE ioctl for unix sockets. This
ioctl opens a file to which a socket is bound and returns a file
descriptor.
This new ioctl allows us to get mnt_id by reading fdinfo, and mnt_id
is enough to find a proper mount point and a mount namespace.
The logic of this patch is straight forward. On dump, we save mnt_id for
sockets, on restore we find a mount namespace by mnt_id and restore this
socket in its mount namespace.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
unix_process_name() are called when sockets are being collected,
but at this moment we don't have socket descriptors.
A socket descriptor is reuired to get mnt_id, what will allow to resolve
a socket path in its mount namespace.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This ioctl opens a file to which a socket is bound and
returns a file descriptor. This file descriptor can be used to get
mnt_id and a file path.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The USK_CALLBACK flag means that a socket is externel and will be
restored by a plugin. open_unixsk_standalone should not be called to
these sockets.
$ make -C test/others/unix-callback/ run
...
(00.109338) 7471: sk unix: Opening standalone socket (id 0xd ino 0 peer 0x63b)
(00.109376) 7471: Error (criu/sk-unix.c:1128): sk unix: BUG at criu/sk-unix.c:1128
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unix file sockets have to be restored in proper mount namespaces.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When walking over unix sockets make sure the
queuer is present before accessing it.
https://jira.sw.ru/browse/PSBM-82796
Reported-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
It is not used, probably was committed by mistake.
Fixes: 2d093a1702 ("travis: add a job to test on the fedora rawhide")
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
In Ubuntu Bionic for armhf, clang is compiled for armv8l rather than
armv7l (as it was and still is for gcc) and so it uses armv8 by default.
This breaks compilation of tests using smp_mb():
> error: instruction requires: data-barriers
The fix is to add "-march=armv7-a" to CFLAGS which we already do,
except not for the tests.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
The newly introduced output of the CRIU and kernel version does not
happen when running CRIU under RPC. This moves the print_versions()
function util.c and calls it from cr-service.c
Signed-off-by: Adrian Reber <areber@redhat.com>
This patch makes restore_one_inotify() to request specific
watch descriptor number instead of iterating in (possible)
long-duration loop if system supports it.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Currently, one feature is supported. Add possibility
for a test to depend on several features.
v2: Delete excess "if" as suggested by Andrey Vagin.
Rename variables to decrise patch size.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need this to save backward compatibility with old images.
It is zero only if it is absent in an image file.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
tun test in nested net ns wrapper.
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
ktkhai: Makefile hunks
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
This adds new tunfile_entry::ns_id field and populates
it in standard socket way. Restore uses this ns_id
to choose correct namespace. Note, we could completelly
skip set_netns() on restore in case of !has_ns_id, but
using top_net_ns invents some definite behaviour.
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
ktkhai: comment written/code movings
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
LAZY_PAGES_SK_OF is need only once for every process,
and it's not frequently used, so we can place it
to fdstore.
https://travis-ci.org/tkhai/criu/builds/343405755
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Sockets are sent via SCM_CREDENTIALS, and this kernel interface
needs to have uid and gid mapped (see __scm_send() in kernel).
So, set them before send_fds() use.
Also, move prep_usernsd_transport() below to be after this
for uniformity.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We've slowed down a little, but still new features and bugfixes appear.
This time we've improved lazy migration, completed SCM messages support,
added nesting netns support (now we have two of them -- net and mnt)
and did many small fixes here and there.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Child may see close() result before it receives signal,
while it shouldn't see it. Instead of games with later
close(), just stop do it. sys_exit() after program finish
will close them all.
Reported-by: Andrey Vagin <avagin@virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we save only attributes with non-zero values. For example,
a default value for IFLA_IPTUN_PROTO is IPPROTO_IPV6 (41), so we have to
save even attributes with zero values.
https://github.com/checkpoint-restore/criu/issues/445
Fixes: 4a044e6af9 ("net: Dump regular sit device")
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We open ns_fd via ioctl(SIOCGSKNS), but never close. Fix that.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
x86's kerndat section in crtools.c has grown too much.
Let's make it more readable and *looking at cleared include-list*,
it'll better parallelize build.
Maybe we should turn __weak function into 0-defines.
Or clean 0-defines with ifdefs in generic file.
I have no strong opinion on that.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The --lazy-migrate option allows testing of lazy migration when running ns
or uns flavor.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
CID 85039 (#1 of 1): Unchecked return value (CHECKED_RETURN)
6. check_return: Calling ptrace without checking return value (as is done elsewhere 44 out of 49 times).
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 155804 (#1 of 1): Unchecked return value (CHECKED_RETURN)
2. check_return: Calling umount2 without checking return value (as is done elsewhere 8 out of 9 times).
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 172198 (#1 of 1): Resource leak (RESOURCE_LEAK)
9. leaked_storage: Variable sk going out of scope leaks the storage it points to.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 154076 (#1 of 1): Unchecked return value from library (CHECKED_RETURN)
1. check_return: Calling setsockopt(sk, 6, 1, &val, 4U) without checking return value. This library function may fail and return an error code.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 161693 (#1 of 1): Resource leak (RESOURCE_LEAK)
5. leaked_storage: Variable new going out of scope leaks the storage it points to.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
*** CID 179043: (USE_AFTER_FREE)
close bfd fd safe so that we won't have double close
*** CID 179041: Resource leaks (RESOURCE_LEAK)
don't forget to close fd on error
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
*** CID 185302: Null pointer dereferences (NULL_RETURNS)
/test/zdtm/static/cgroup_ifpriomap.c: 107 in read_one_priomap()
>>> Dereferencing a pointer that might be null "out->ifname" when calling "strncpy".
There is also a warning about using rand(), but..
Not sure that we need to entangle everything just for pleasing Coverity:
>>> CID 185301: Security best practices violations (DC.WEAK_CRYPTO)
>>> "rand" should not be used for security related applications, as linear congruential algorithms are too easy to break.
Leaving that as-is and marking in Coverity as WONTFIX.
Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I've also dropped `noauto' in this patch, reverting the
commit be98273cf1 ("zdtm: mark static/cgroup_ifpriomap as noauto")
Don't see any sense to separate it as another patch.
Fixes: #383
Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently, if pipe is shared between lazy and non-lazy PPBs lazy migration
fails because data that should be transfered on demand is spliced into the
images. Preventing pipe sharing between PPBs of different type resolves
this issue.
In order to still minimize pipe fragmentation, we track the last pipe that
was used for certain PPB type and re-use it for the PPB of the same type.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As it's aligned to 16, all structures that contain it should be
also aligned to 16. In the kernel there is no such align as
there two separate definitions of i387_fxsave_struct:
one for ia32 and another for x86_64.
Fixes newly introduced align warning in gcc-8.1:
In file included from compel/include/uapi/compel/asm/sigframe.h:7,
from compel/plugins/std/infect.c:13:
compel/include/uapi/compel/asm/fpu.h:89:1: error: alignment 1 of 'struct xsave_struct_ia32' is less than 16 [-Werror=packed-not-aligned]
} __packed;
^
It doesn't change the current align of the struct, as containing
structures are __packed and it aligned already *by fact*.
It only affects the function users of the struct's local variables:
now they lay aligned on a stack.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It helped a bit to debug Skylake ptrace() bug, let's put it in.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Ugh, I've spent 25 mins at 4 A.M. to figure out why the tests are failing.
And the reason is stupied me, who defined a new flag after 0x8
as 0x16, not as 0x10. Simplify those definitions for such simple-minded
living creatures like Dima.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On Skylake processors and kernel older than v4.14
ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, iov)
may return not full xstate, ommiting FP part (that is XFEATURE_MASK_FP).
There is a patch which describes this bug:
https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1318800.html
Anyway, it's fixed in v4.14 kernel by (what we believe with Andrey) this:
https://patchwork.kernel.org/patch/9567939/
As we still support kernels from v3.10 and newer, we need to have a
workaround for this kernel bug on Skylake CPUs.
Big thanks to Shlomi for the reports, the effort and for providing an
Amazon VM to test this. I wish more bug reporters were like you.
Reported-by: Shlomi Matichin <shlomi@binaris.com>
Provided-test-env: Shlomi Matichin <shlomi@binaris.com>
Investigated-with: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Mere cleanup. For Skylake workaround I'll call one after another,
so it's better separate it in a small helpers.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
get_task_regs() needs to know if it needs to use workaround
for a Skylake ptrace() bug. The next patch will introduce a
new flag for that.
I also thought about making 3 versions of get_task_regs() and
adding them to ictx->get_task_regs() depending on the flags..
But get_task_regs() is a private function and infect_ctx is
a uapi.. So, let's just pass context flags to get_task_regs().
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As we anyway define save_regs_t for other purposes,
use it in the function declaration.
To unify infect_ctx style, add make_sigframe_t.
Mere cleanup.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to know if ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, iov)
returns xsave without FP state part.
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Error-path for failed fork().
Looks originally forgotten, oops!
Also print a message on failed fork().
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We ignore restore_one_*notify() error code, while we mustn't.
Make open function fail when we can't restore them.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Imagine, we have to restore inotify with watch descriptor 0x34d71d6.
Then we have:
1.235021 5578: fsnotify: Watch got 0x1 but 0x34d71d6 expected
...
...
527.378042 5578: fsnotify: Watch got 0x34d71d3 but 0x34d71d6 expected
527.378042 5578: fsnotify: Watch got 0x34d71d4 but 0x34d71d6 expected
527.378042 5578: fsnotify: Watch got 0x34d71d5 but 0x34d71d6 expected
Stop doing this and stop generating GBs of debug messages.
We already have print message before restore_one_inotify().
Let's add just one more after it.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This test makes looped unix sockets queues and tries
to iterate over them after the restore.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Everything is ready. Message queue restores are in
the second stage of open for all types of unix sockets.
We just need to make scm wait before restore_unix_queue()
and allow to dump such scm context.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we allow unix sockets sent over unix sockets,
dump_sk_queue() may dump and resolve some peers.
So, we need run it firstly and avoid linking our
peer_node to peer's peer_list.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Similar to previous patch, this makes the second end
of dgram socketpair to be open till post open. This
allows to delay restore of message queue.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This makes the second end of socketpair to live till post_open.
We need it alive if we want to restore message queue later.
Otherwise, we do not have a queuer, which fd is used to actually
write messages.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Extract the functionality, which makes socket memory initialization.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This function will be used to allocate id for fake files
(don't confuse with fake fds, e.g. fles).
Suggested-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
restore_sk_common() may shutdown a socket, and queuer
won't be able to connect to it. So, this action must
be postponed.
We have this problem since long ago, but we are lucky
we haven't bumped in it.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Actually, there is no functional changes. We just postpone
restore of the queues. This will be used in the further
patches to restore unix sockets sent over unix sockets.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After previous patch, master and slave ends of socketpair
are owned by the only task. So, we may avoid using
of send_desc_to_peer() of the second end, and just
reopen it with right pid.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We're going to split interconnected pair restore
on two stages. Since we need the second end
to restore message queue in (future) post open,
we add it to the process, who is owner of the first
end.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since new file engine was introduced, we don't care
which particular pid should be master or slave.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This adds a new argument and changes debug print
(it will be used for any fle, not only for scm).
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This functional allows to make a fle a master on
the time of collection. We will use it to add fake
files when we need to do this after add_fake_fds_masters().
This will be used to add second end of socketpair as
a fake fle (as the first end is placed in the right
place, we will force add the second end there).
See next patches.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since this function is used by standalone sockets only,
we move it to appropriate place. No functional changes.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since epoll restore is split in two parts,
epoll_create() does not depend on another
files state. Since epoll is created, it
can be sent to everywhere. So, there is
no circular dependences, and we allow epolls
sent over unix socket.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Create socketpair and epoll. Add one end of the socketpair
to epoll and then twice send it over another end.
After restore check, that epoll can be received
via socket, and that it contains event.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
$ make lint
flake8 --config=scripts/flake8.cfg test/zdtm.py
test/zdtm.py:323:19: F841 local variable 'e' is assigned to but never used
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
waitpid() does not return child pid, when child has not exited.
So, we can't use it to find pids of children.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
close_safe can operate uninitialized fd in case of error in switch_ns,
found by Coverity Scan:
*** CID 187164: Uninitialized variables (UNINIT)
/criu/mount.c: 1313 in open_mountpoint()
1307 err:
1308 return 1;
1309 }
1310
1311 int open_mountpoint(struct mount_info *pm)
1312 {
>>> CID 187164: Uninitialized variables (UNINIT)
>>> Declaring variable "fd" without initializer.
1313 int fd, cwd_fd, ns_old = -1;
1314
1315 /* No overmounts and children - the entire mount is visible */
1316 if (list_empty(&pm->children) && !mnt_is_overmounted(pm))
1317 return __open_mountpoint(pm, -1);
1318
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Start test
./mxcsr --pidfile=mxcsr.pid --outfile=mxcsr.out
Run criu dump
Unable to kill 44: [Errno 3] No such process <--------------- this one
Run criu restore
Run criu dump
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Write a nullbyte only if there is enought space for it.
Cc: Stephen Röttger <stephen.roettger@gmail.com>
Reported-by: Stephen Röttger <stephen.roettger@gmail.com>
Signed-off-by: Andrei Vagin <avagin@openvz.org>
We print errors in all error cases when calling linkat_hard anyway, but
for some errors like EEXIST we are fine and just skip them, so we should
not print error here.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is a test for convert_path_from_another_mp fix, it is a bit tricky as
we don't fully support ghosts on readonly fs, but only if the ghost can
be remaped on some _other_ bindmount (luckily we have same ghost on other
bind). Moreover wrong absolute path generated with old convert_path_from
_another_mp for lnkat don't always fail, only in case we want to do
linkat on mount in _other_ mountns and absolute path makes us do it in
local mountns and local path is readonly and we fail. =)
v2: remove unused headers
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If dmi->ns_mountpoint is "/" then in dst we will return "/..." -
absolute path but we want here path relative to dmi mount. Adding "./"
before the path guaranties that it will be always relative.
https://jira.sw.ru/browse/PSBM-72351
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Fork tasks and create fds with different numbers.
Some children share file with parent (CLONE_FILES).
Check, than we can suspend and resume in this case.
v2: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently, we set rlim(RLIMIT_NOFILE) unlimited
and service_fd_rlim_cur to place service fds.
This leads to a signify problem: every task uses
the biggest possible files_struct in kernel, and
it consumes excess memory after restore
in comparation to dump. In some situations this
may end in restore fail as there is no enough
memory in memory cgroup of on node.
The patch fixes the problem by introducing
task-measured service_fd_base. It's calculated
in dependence of max used file fd and is placed
near the right border of kernel-allocated memory
hunk for task's fds (see alloc_fdtable() for
details). This reduces kernel-allocated files_struct
to 512 fds for the most process in standard linux
system (I've analysed the processes in my work system).
Also, since the "standard processes" will have the same
service_fd_base, clone_service_fd() won't have to
actualy dup() their service fds for them like we
have at the moment. This is the one of reasons why
we still keep service fds as a range of fds,
and do not try to use unused holes in task fds.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
v2: Add a handle for very big fd numbers near service_fd_rlim_cur.
v3: Fix excess accounting for nr equal to pow 2 minus 1.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In normal life this is impossible. But in case of big
fdt::nr number (many processes, sharing the same files),
and custom service_fd_base, normal (!CLONE_FILES) child
of such process may have overlaping service fds with
parent's fdt. This patch introduces "memmove()" behavior
(currently there is "memcpy()" behavior) and this will
be used in next patch.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch just moves part of clone_service_fd()
to separate function, that change readability of the code.
There are no functional changes, only refactoring.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch makes the call of service fds relocation after
root_prepare_shared()->prepare_fd_pid(). Next patches
will make service_fd_base depend on task's max fd used,
and for root_item we need to read all fles to know
the maximum of them.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Next patches will make service_fd_base not contant.
It will be "floating" and change from task to task.
This patch makes preparation for that: it closes
old service fd after it's duplicated.
Currently the code is unused as in case of
!(rsti(me)->clone_flags & CLONE_FILES), the child
has the same id as its parent, and the duplication
just does not occur.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch counts maximum of inherited fds.
The value will be used in next patch.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Next patches will make service fds numbers not connected
not rlimit. Change the name to better fit its goal.
Also, leave service_fd_rlim_cur variable to have cached
access to rlimit value.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
v2: More comments
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Mark area, where service fds modifications are prohibited.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch populates/occupies PROC_FD_OFF fd number,
which is goint to be replaced atomically in next patches.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch populates and occupies ROOT_FD_OFF fd,
which guarantees it won't be reused by ordinary fds.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch introduces sfds_protected, which allows
to mask areas, where modifications of sfds are prohibited.
That guarantees, that populated sfds won't be reused.
v4: New
v5: Add comment and print sfd type before BUG().
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Function to print call trace of a process.
Borrowed from this fm:
https://www.gnu.org/software/libc/manual/html_node/Backtraces.html
backtrace() and backtrace_symbols() are not implemented in alpine,
so we use __GLIBC__ ifdef to do not compile this function there.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Net namespace does not act on /proc/[pid] context,
so this close is completely useless.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1)Further mntns_set_root_fd() calls install_service_fd(),
which silently closes already open fd. So, kill close_service_fd()
and make __mntns_get_root_fd() atomical in ROOT_FD_OFF modifications.
2)close_pid_proc() is not need here, as it's about root_item's
/proc directory and __mntns_get_root_fd() actions don't act on it.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Here we need to close proc self fd only, as it's not
a service fd, and it can occupy real task fd number.
Closing of PROC_PID_FD_OFF is useless action here,
because it's already occupy a service fd number.
So, we skip this excess syscall, and leave PROC_PID_FD_OFF
open.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Place stdin in fdstore. Kill SELF_STDIN_OFF.
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Next patch will move SELF_STDIN_OFF sfd to fdstore.
This patch moves fdstore_init() before tty_prep_fds().
v4: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Create a zombie with specific pgid and check that
pgid remains the same after restore.
This test hangs criu restore without any of two previous patches:
1)without "restore: Call prepare_fds() in restore_one_zombie()"
in 100% cases;
2)without "restore: Split restore_one_helper() and wait exiting
zombie children" fail is racy, but you can add something like
criu/cr-restore.c:
## -1130,6 +1130,8 @@ static int restore_one_zombie(CoreEntry *core)
if (task_entries != NULL) {
restore_finish_stage(task_entries, CR_STATE_RESTORE);
+ if (current->parent->pid->state == TASK_ALIVE)
+ sleep(2);
zombie_prepare_signals();
}
and it will fail with almost 100% probability.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Cleanup fork() definition and make a generic function
for all archs. It may be useful, when you want to add
more clone flags to fork(), or if you want to pass more,
than one argument to child function (glibc's clone
alows only one).
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Zombie is also can be choosen as a parent for task helper like
any other task.
If the task helper exits between restore_finish_stage(CR_STATE_RESTORE)
and zombie_prepare_signals()->SIG_UNBLOCK, the standard criu SIGCHLD
handler is called, and the restore fails:
(00.057762) 41: Error (criu/cr-restore.c:1557): 40 exited, status=0
(00.057815) Error (criu/cr-restore.c:2465): Restoring FAILED.
This patch makes restore_one_zombie() behave as restore_one_helper()
and to wait children exits before allowing SIGCHLD. This makes us
safe against races with exiting children.
See next patch for test details.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Zombie may be choosen as parent for task helper
during solving pgid dependences. In this situation,
it becomes to share fdt with the helper and it has
to call prepare_fds() to decrement fdt->nr.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CTL_TTY_OFF and reserve_service_fd() are unused now,
so purge them from the code.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are two problems. The first is CTL_TTY_OFF occupies
one of the biggest available fds in the system. It's a number
near service_fd_rlim_cur. Next patches want to allocate
service fds lower, than service_fd_rlim_cur, and they want
to know max used fd from file fles after the image reading.
But since one of fds is already set very big (CTL_TTY_OFF)
on a stage of collection fles, the only availabe service
fds are near service_fd_rlim_cur. It's vicious circle,
and the only way is to change ctl tty fd allocation way.
The second problem is ctl tty is ugly out of generic file
engine fixup (see open_fd()). This is made because ctl tty
is the only slave fle, which needs additional actions
(see tty_restore_ctl_terminal()). Another file types just
receive their slave fle, and do not do anything else.
This patch moves ctl tty to generic engine and solves all
the above problems. To do that, we implement new CTL_TTY
file type, which open method waits till slave tty is received
and then calls tty_restore_ctl_terminal() for that. It fits
to generic engine well, and allocates fd via find_unused_fd(),
and do not polute file table by big fd numbers.
Next patch will kill currently unneed CTL_TTY leftovers
and will remove CTL_TTY_OFF service fd from criu.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Move the function and reduce its arguments number.
This is cleanup needed to keep all tty code together.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Just mark the fle as "fake" and the engine will do all the work.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
service_fd_id is id of a specific task, while other tasks
in shared fd table group may have bigger id numbers.
In this case given unused fd intersects with service fds
of such tasks. This leads to undefined behaviour. Fix that.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch speeds up creation of child process by disabling
iteration over open files for the most cases. Really, we don't
need that now, as previous patches make parent files do not leak:
mnt namespace fds are stored in fdstore, pid proc files
are closed directly.
So, now we can skip closing old files for the most cases,
except some CLONE_FILES cases: we need that only if parent
have CLONE_FILES in its flags (and for root_item).
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When task is in pid namespace, getpid() can't be used
to identify it. So, use vpid instead of that.
Also, move log_init_by_pid() above pid check.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Child does not know about parent's pid proc fd,
and it can't close it by fd. Next patch will do
close_old_files() optional, and it will base on
the fact there is no leftover fds. So, close pid
proc directly.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This allows to decrese number of file descriptors,
which are passed to children, and that is need to
close in close_old_files().
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>:
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
mntns_get_root_fd() may be called by a task from
!root_user_ns, and it fails if so.
Put root fd to fdstore to allow use it every task.
v3: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CR_PROC_FD_OFF is need for accessing to foreign tasks
fds, and will be used in the future.
TRANSPORT_FD_OFF is for uniformity.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I need named socket to communicate with pid_ns helpers
(see next patches) and receive answer from them
(it's impossible to send answer to unnamed socket).
As we already have transport socket, we'll reuse it
for the above goal too.
This patch makes transport sockets be created before
creation of children tasks. Also, now they are created
not only for alive tasks (so we need additional
manipulations for TASK_HELPERS, e.g., to call prepare_fdt()).
v5: Return CLONE_FILES clone() argument during task helpers
creation. Also get rid of fdt_mutex as CLONE_FILES processes
does not close old files after clone, and we don't have
intertersections between them. Also, socket() system call
can't return a fd in service fds range, which was the main
reason to have this mutex.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Next patches will create transport sockets in task helpers.
As helpers are forked using CLONE_FILES, they must resolve
shared fds to create their own service fds. This patch allows
that.
I've digged in the code, and there is no a reason, we need
pid_rst_prio() during choosing of fdt restorer. So, this
case may be safely deleted, which guarantees, that in case
of TASK_HELPER, the restorer of fdt will be parent, i.e.,
no one TASK_HELPER will be restorer of fdt.
v5: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is refactoring, which will be used in next patches.
BUG_ON() just to mention that parent must be set before
call of this function.
v5: New
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We close it in sigreturn_restore() for unification with other
service fds, so kill the second close() from here.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This minimize chances to hit problem where files
used for page transfer are trying to use same number
reserved for service fd.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Will need it to unlimit the files allocation
for service fd reserving and later for parasite code run
(which is implemented in vz7 instance and soon will be
ported into vanilla).
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add a fake fd type for autofs. This allows functions
like find_file_desc() work as expected, without
having two different file_desc with the same type
and same id.
Also, later, it will allow to delete autofs_create_fle()
and to use generic helper.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unchanged test provided by Andrew.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case we have mounts:
1 /mnt/
2 /mnt/a with parent 1
3 /mnt/a/b with parent 1
4 /mnt/a with parent 2
We determine 2 as needing remap with does_mnt_overmount() and remap it.
Next we mount 4 on top of 2. Next in fixup_remap_mounts() we want to
move 2 back to it's parent 1, but instead move 4 there. So in these case
children-overmounts need to be remapped too.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Remaps in mnt_remap_list should follow same descending order which was
setup in mnt_resort_siblings(), so don't reorder them.
For instance if we have sibling mounts with mountpoints:
1) /dir1/dir2/dir3
2) /dir1/dir2
3) /dir1
Here (2) is sibling-overmount for (1). Mount (3) is sibling-overmount
for both (1) and (2). So when we move overmounts back in
fixup_remap_mounts() we should first move (2) and only then (3).
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We should add new entry _before_ first entry with less depth to sort in
descending order.
e.g: entries in list have depths [7,5,3], adding new entry m with depth
4 we would break list_for_each_entry loop on p with depth 3, before
patch we would get [7,5,3,4] after list_add, which is wrong.
Also we can relax "<=" check to "<" to avoid unnecessary reordering.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
dump of VZ7 ct fails, if we have overmounted tmpfs inside:
[root@silo ~]# prlctl enter su-test-2
entered into CT
CT-829e7b28 /# mkdir /mnt/overmntedtmp
CT-829e7b28 /# mount -t tmpfs tmpfs /mnt/overmntedtmp/
CT-829e7b28 /# mount -t tmpfs tmpfs /mnt
CT-829e7b28 /# logout
[root@silo ~]# prlctl suspend su-test-2
Suspending the CT...
Failed to suspend the CT: PRL_ERR_VZCTL_OPERATION_FAILED (Details: Will skip in-flight TCP connections
(01.657913) Error (criu/mount.c:1202): mnt: Can't open ./mnt/overmntedtmp: No such file or directory
(01.662528) Error (criu/util.c:709): exited, status=1
(01.664329) Error (criu/util.c:709): exited, status=1
(01.664694) Error (criu/cr-dump.c:2005): Dumping FAILED.
Failed to checkpoint the Container
All dump files and logs were saved to /vz/private/829e7b28-f204-4bce-b09f-d203b99befd4/dump/Dump.fail
Checkpointing failed
)
Criu wants to dump the contents of /mnt/overmntedtmp/ mount but it is
unavailable. So we copy the mount namespace in such a case and unmount
overmounts to access what we want to dump.
Actual usecase here is dumping CT with active mariadb and ssh
connection. Together they happen to create such overmount. As by default
systemd creates a separate mount namespace for mysql and also mounts
tmpfs to /run/user in it, and when ssh(root) is connected - systemd also
mounts tmpfs in container root mount namespace to /run/user/0 for user
files. As /run is slave mount /run/user/0 also propagates to mysql's
mount namespace and initially becomes overmounted by /run/user.
https://jira.sw.ru/browse/PSBM-57362
remove __maybe_unused for mnt_is_overmounted and umount_overmounts
changes in v2:
1) Use clone not fork, share resources with parent same as in
call_in_child_process.
2) Do not enter userns (create helper) for non-overmounted mounts. Thus
return back setns/resorens logic.
3) Helper opens fd for parent directly due to CLONE_FILES, remove futex.
4) Check helper exit status properly.
5) Add get_clean_fd helper.
6) Add better comments.
changes in v3:
1) Pass fd from helper through args instead of ret code, fix ret code
checking.
2) Add \n to pr_err in open_mountpoint
changes in v5:
Make comments even better.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
also remove __maybe_unused for __umount_children_overmounts
note: leave it __maybe_unused yet
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The origin idea was to set --empty net for criu dump and criu restore,
but before cde33dcb06 ("empty-ns: Don't C/R iptables too (v2)"),
criu restore worked without --empty net and we didn't notice that
docker doesn't set this option on restore.
After a small brainstorm, we decided that it is better to remove
this requirement. Docker has to set this option, but with this changes,
the docker issue will be less urgent.
https://github.com/checkpoint-restore/criu/issues/393
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There's a
if (bad_thing) {
ret = -1;
break;
}
code above this hunk, whose intention is to propagate -1 back to
caller. This propagation is obviously broken.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
runc restore executes criu with --emptyns network and set
a setup-namespaces script to restore a network namespace.
https://github.com/xemul/criu/issues/314
Looks-good-to: Pavel Emelyanov <xemul@virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Fixes: 2189b9c71d3d ("net: allow to dump and restore more than one network namespace")
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Picked from patch "[PATCH RFC] namespaces: use CLONE_VFORK
with CLONE_VM when it is possible" by Andrew Vagin.
Currenly parent touches child's stack, as in moment of clone() call
its stack pointer is above the child's (we allocate char stack[128]
on parent's stack). This prevents to create CLONE_VM|CLONE_VFORK
processes, because the child uses stack addresses occupied by parent.
The patch changes clone_noasan() behaviour and allows to do that
with the same memory consumption. We give a child memory, which
is not used by parent clone(), so parent's and child's stacks
have no tntersection.
This allows to create CLONE_VM|CLONE_VFORK processes.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
(Was "user_ns: Block SIGCHLD during namespaces generation")
We don't want asynchronous signal handler during creation
of namespaces (for example, in create_user_ns_hierarhy())
as we do wait() synchronous. So we need to block the signal.
Do this once globally.
v2: Set initial ret = 0
v3: Block signal globally in root_item before its children
are created.
v4: Move block to prepare_namespace()
Suggested-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In next patches usernsd will need to create transport
socket in the same net_ns as other tasks do their
TRANSPORT_FD_OFF sockets.
Choose criu net_ns for that: this allows usernsd
to do not wait for creation of other net_ns, i.e.
to do not introduce new dependencies between tasks.
In case of (root_ns_mask & CLONE_NEWUSER) != 0
root_item's user_ns does not allow to restore criu net_ns,
so do prepare_net_namespaces() in sub-process to do not
lose criu net.
v3: Introduce __prepare_net_namespaces and execute it in cloned task.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since net ns is assigned after prepare_fds() and,
in common case, at the moment of open_ns_fd() call
task points to a net ns, which differs to its target
net ns, we can't get the ns from a task. So, get it
from fdstore. Also, support userns ns fds.
v2: Add comment
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We shave a test case for external veth devices. This test case
checks veth devices which are living in two dumped network
namespaces.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
A network device, which is connected to a bridge, is restored
after the bridge. In this case we can set the master attribute and
the device will be connected to the bridge automatically.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we dump a veth device, the kernel reports where a peer device lives
and we use this information to restore this veth pair.
On restore we set a net ns id for a peer and it is created in the required
netns.
v2: add more comments
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In each network namespace we can set an id for another network namespace
to be able to address it in netlink messages.
For example, we can say that a peer of a veth devices has to be created
in a network namespace with a specified id. If we request information about
a veth device, a kernel will report where a peer device lives.
An user are able to set this ID-s, so we have to dump and restore them.
v2: add more commetns
v3: make a union of nsfd_id and ns_fd, they are not used together
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Each network namespaces has a list of ID-s for other namespaces,
so if we request infomation about a veth device, we get an id
for a namespace of a peer device.
These ID-s can be set by users or by kernel when they are required.
CRIU has to restore these ID-s for network namespaces. We have to
remember that one netns can have different id-s in different network
namespaces.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is possible to assign id for network namespaces and
this id will be used by the kernel in some netlink messages.
If no id is assigned when the kernel needs it, it will be
automatically assigned by the kernel.
For example, this id is reported for peer veth devices.
v2: add a comment
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This tests create a few processes which live in three network namespaces
and have a few sockets which are created in different network namespaces.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Each sockets belongs to one network namespace and operates
in this network namespace.
socket_diag reports informations about sockets from
one network namespace, but it doesn't report sockets which
are not bound or connected to somewhere. So we need to have
a way to get network namespaces for such sockets.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This ioctl is called for a socket and returns a file descriptor
for network namespace where a socket has been created.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Each socket has to be restored from a proper network namespaces
where it was created.
We set a specified network namespace before restoring a socket.
A task network namespace is set after restoring all files.
v2: don't set the root netns for transport sockets
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need this to avoid conflicts with file descriptors,
which has to be restored.
Currently open_proc_pid() doesn't used during restoring
file descriptors, but we are going to use it to restore
sockets in proper network namespaces.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Restore all network namespaces from the root task and then set
a proper namespace for each task after restoring sockets, because
we need to switch network namespaces to restore sockets.
Each socket has to be created in a proper network namespace.
v2: fix a typo bug
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Each socket has to be restored in a proper namespaces where
it has been created.
Here is an issue about unconnected and unbound sockets,
they are not reported via socket-diag and we can't to
get their network namespaces.
v2: add a comment before get_socket_ns()
remove nsid from sk_packet_entry
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
PID ussualy means processs ID, but prepare_net_ns works with namespaces.
travis-ci: success for Dump and restore nested network namespaces (rev4)
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
ns_id will be used to collect sockets and other per-netns
resources
travis-ci: success for Dump and restore nested network namespaces (rev4)
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
There are a number of global variables around this descriptor
(e.g. open_proc_fd) and their values are saved in memory which
are not shared between processes.
travis-ci: success for Dump and restore nested network namespaces (rev4)
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This time we shifted the update one month, due to the amount of
changes not being very big. And got pretty big update, including
a set of bugfixes and new functionality.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It has two arguments "pos_l and "pos_h" instead of one "off". It is used
to handle 64-bit offsets on 32-bit kernels.
SYSCALL_DEFINE5(preadv, unsigned long, fd, const struct iovec __user *, vec,
unsigned long, vlen, unsigned long, pos_l, unsigned long, pos_h)
https://github.com/checkpoint-restore/criu/issues/424
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Due to way CRIU handles paths (as relative to workdir), there's a case,
where migration would fail. Simple example is a ghost file in filesystem
root (with root being cwd). For example, "/unlinked" becomes "unlinked".
And original code piece scans path for other slashes, which would be
missing in this case. But it's still a perfectly valid case, and there's
no need to fail. So if there's no parent dir - we just don't need to
create one and we can just return 0 here instead of failing.
Signed-off-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The kernel doesn't have an interface to get a sent queue for udp
sockets, so currently we can't dump them and criu dump has to fail in
such cases.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now we block all sockets with non-zero idiag_wqueue, but it doesn't mean
that a CORK option is enabled for a socket. A packet can be in a network
stack and it is accounted into idiag_wqueue.
https://github.com/checkpoint-restore/criu/issues/409
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Except for several false positives done by:
find -type f -name "*.c" -not -path "./test/*" -exec sed -i
's/\(\<pr_err.*[^\][^n]\)\("[,)]\)/\1\\n\2/g' {} \;
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Leases can be set only on regular files. Thus, as optimization we can
skip attempts to find associated leases in 'correct_file_leases_type'
for other fd types.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
-- check childs' errors in file_leases03
-- test c/r of lease transfered to child process
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CRIU creates dictinct lock record for each file descriptor on the same
OFD. The patch removes this duplicates. To do so, it adds new field into
struct file_lock, which stores pid of fd, on which lock was found.
'owner pid' is not actually helpful, because the original fd, on which
lock have been set, can be already closed.
Also it purges crutches doing the same stuff but only for file leases.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Test cases:
0. Basic non-breaking read/write leases.
1. Multiple read leases and OFDs with no lease for the same file.
2. Breaking leases.
3. Multiple fds (dup + inherited) for single lease (mutual OFD).
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Information about locks in /proc/<pid>/fdinfo is presented only since
kernel v4.1. This patch adds logic to *note_file_lock* to match leases
and OFDs.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
restore of breaking leases is executed in 2 steps:
1. restore the lease in a state it was before break
2. break it by opening associated file.
The patch fixes type of broken leases to 'target lease type',
because procfs always returns 'READ' in this case.
Also, it adds 'updated' field in lock structure. It's used to remove all
duplicated records for single lease from the image, which wasn't
corrected by 'correct_lease_type'.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Leases in breaking state are not supported. In that case criu will
report an error during the dumping. Also lock info in
/proc/<pid>/fdinfo should be presented (since kernel 4.1).
Before taking out new lease it modifies process fsuid to match file uid
(see fcntl F_SETLEASE).
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now it's probably one valide use case, because there is no way to commit
a container when a container is being checkpointed.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
All static tests has to stop any activity before C/R.
./tempfs_subns --pidfile=tempfs_subns.pid --outfile=tempfs_subns.out --dirname=tempfs_subns.test
Run criu dump
Unable to kill 128: [Errno 3] No such process
Run criu restore
7: Old mounts lost: []
7: New mounts appeared: [('/rootfs/criu/test', '/'), ('/', '/proc'), ('/', '/dev/pts')]
:
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we use an additional pipe to steal data from a pipe, but we
don't check that we steal all data. And the additional pipe can have a
smaller size.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
a) As we shmalloced rpath it can not be xfreed. b) As we shmalloc
variables in collect_remap_ghost() far away from open_remap_ghost()
where we want to free them, there is no guaranty that our shmalloc was
last and we can't use shfree_last().
fixes commit 0c675a5e9d ("files: remove link_remaps when everything
has been restored")
When create_ghost() fails for some reason that produces a segfault for me.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reading and writing large buffers may result in short read/write. In cases
we expect the entire buffer to be transferred use {read,write}_data rather
than plain read/write syscalls.
Reported-by: Mr Jenkins
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Some tests expect that all the data will be handled in a single invocation
of read/write system call. But it possible to have short read/write on a
loaded system and this is not an error.
Add helper functions that will reliably read/write the entire buffer.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If we start backroung memory fetch before restore is completely finished,
we may try to write to the memory areas which were not yet remapped to
proper place and are not registered with userfaultfd.
Add synchronization between restore and the lazy-pages so that lazy-pages
will only handle #PFs before all the tasks are restored.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The remote page read has nothing to do if the page-server on the source has
closed the connection. Just report an error and abort.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently when we poll a file descriptor, we only process EPOLLIN events
and if a connection is closed the receiving side has no means to deal with
it.
Add a callback for EPOLL{RD}HUP events and the default implementation for
these events that removes the file descriptor from epoll and closes it.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
A bit more readable and will be easy to distinguish from upcoming
hevent^Whangup_event.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The generic epoll_wait wrapper should not do any assumptions about timeout.
It's it up to lazy-pages daemon to make (future) policy decisions.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If we receive only part of the IOV from the page-server we recalculate the
IOV so it will point to the area we still have to fetch. During the split,
the IOV covering the remaining area may remain marked as 'queued' and we'll
never retry fetching it.
Marking the IOV as not queued will ensure its pages will be requested
again.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since commit e609267f681062b4370e528a50f635222e0c2330 ("page-pipe: allow to
share pipes between page pipe buffers") the assumption that we will receive
the exact amount of pages we've requested with PS_IOV_GET does not always
hold.
In the case we serve pages data from the images using 'page-server
--lazy-page' the IOVs seen by the pagemap may cross page-pipe buffer
boundaries and read_page_pipe will clamp the pages in the response to those
boundaries.
Adjust page_server_read so it will not try to receive more pages than
page-server is going to send.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now criu create a new pipe buffer, if a previous one has another set of
flags. In this case, a pipe is not full and we can use it for the
next page buffer.
We need 88 pipes to pre-dump the zdtm/static/fork test without this
patch, and we need only 17 pipes with this patch.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
v2: and move it upper, because it is going to be used in ppb_alloc()
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
vmsplice can't splice more than UIO_MAXIOV, but we can
call it a few times from a parasite.
v2: s/nr/nr_segs/
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In addition to writing the CRIU version to the log file this adds the
current kernel version to the log file:
(00.000008) Version: 3.5 (gitid v3.5-511-ga8cc6cf)
(00.000303) Running on node01 Linux 3.10.0-513.el7.x86_64 #1 SMP Tue Feb 29 06:78:90 EST 2017 x86_64
v2:
- small changes as suggested by Dmitry (thanks)
Signed-off-by: Adrian Reber <areber@redhat.com>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If ipv6 socket has an IPv4-mapped address, it is used to handle ipv4
connection, so we have to use ipv4 iptables rules to block this
connection.
Reported-by: Mr Jenkins
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we use the "map_files/%p-%p" format, but actually it should
be "map_files/%lx-%lx".
The kernel could handle both formats, but recently Alexey Dobriyan fixed
the kernel and it accept only the second format.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We always ask users what version of criu they use to investigate a problem,
so it better to have it in a log.
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Reviewed-by: Dmitry Safonov <0x7f454c46@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
criu and soccr has different values for log levels, so
someone has to remap them.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This can help to investigate logs from Mr Jenkins.
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When inotify is laying on uovermounted fs we should walk over
all mountpoints with same s_dev to find openable path.
Note on restore the path is usually already allocated during
dump stage so get_mark_path won't call for open_handle(), in
turn on dump stage the positive return from open_handle()
will cause fsnotify engine to find openable path, thus there
is kind of double work to be optimized in future.
For example we got a container where systemd-udevd inside
opens inotify for /dev/X entry then overmount ./dev path
with slave option and in result irmap engine on predump
can't figure out where the inotify is sitting causing
migrtion to abort.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
config.h is a generated file with "build-features" defines.
We use it for several purposes:
o to check that compiler can do it's job
o to complement user-visible API between distributions
o to add compile-time options from .config global file
It's used in criu and soccr, but compel also needs such thing.
Previously, soccr has a link to config.h in criu includes,
but it would be much cleaner to move it to other headers,
that are shared between sub-projects into include/common.
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Tested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Distributions starts to supply GCC that is configured to compile
-pie and -fPIC code by default due to security reasons.
CONFIG_COMPAT was unfriendy to -pie by the reason of R_X86_64_32S
relocation in call32.S helper:
LINK criu/criu
/usr/bin/ld: criu/arch/x86/crtools.built-in.o: relocation R_X86_64_32S against `.text' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
make[1]: *** [criu/Makefile:92: criu/criu] Error 1
make: *** [Makefile:225: criu] Error 2
Use %rip-relative addressing to avoid ld errors for shared binary linking.
Puff, all needs to be done with bare hands!
Now CONFIG_COMPAT can be used with -pie binaries and all should
also work for debian toolchain (#315).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In this case we can wait it and get an exit code.
For example, it will be useful for p.haul where one connection
is used several times, so we need a way how to understand that
page-server exited unexpectedly.
v2: don't write ps_info if a start descriptor isn't set
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This file is not executable directly, so it should not have the shebang.
Signed-off-by: Avindra Goolcharan <aavindraa@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
warning: In the GNU C Library, "major" is defined
by <sys/sysmacros.h>. For historical compatibility, it is
currently defined by <sys/types.h> as well, but we plan to
remove this soon. To use "major", include <sys/sysmacros.h>
directly. If you did not intend to use a system-defined macro
"major", you should undefine it after including <sys/types.h>.
if (major(st.st_rdev) != major(st_rtc.st_rdev) ||
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
aio_context_t is 8 byte long so on 32 bit mode it might be
strippped off when unsigned long used instead. Fix this typo.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
v2: defining crit_bin and using it for Popen() // Mike
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The number of pipes are limited in a system, so it is better to know how
many we use.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
IPv6 listening sockets can accept both ipv4 and ipv6 connections,
in both cases a family of an accepted socket will be AF_INET6.
But we have to send tcp packets accoding with a connection type.
------------------------ grep Error ------------------------
(00.002320) 53: Debug: Will set rcv_wscale to 7
(00.002325) 53: Debug: Will turn timestamps on
(00.002331) 53: Debug: Will set mss clamp to 65495
(00.002338) 53: Debug: Restoring TCP 1 queue data 2 bytes
(00.002403) 53: Error (soccr/soccr.c:673): Unable to send a fin packet: libnet_write_raw_ipv6(): -1 bytes written (Network is unreachable)
(00.002434) 53: Error (criu/files.c:1191): Unable to open fd=3 id=0x6
(00.002506) Error (criu/cr-restore.c:2171): Restoring FAILED.
------------------------ ERROR OVER ------------------------
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The SO_REUSEPORT option allows multiple sockets on the same
host to bind to the same port. This option has to ve restored when all
sockets are bound to a port. The same logic is already used to restore
SO_REUSEADDR.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Regs are present in unsigned format so convert them
into signed first to provide results.
In particular if memfd_create syscall failed we won't
notice -ENOMEM error but rather treat it as unsigned
hex value
| (05.303002) Putting parasite blob into 0x7f1c6ffe0000->0xfffffff4
| (05.303234) Putting tsock into pid 42773
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In CT, we do:
mkdir -p /a/b/c1
mkdir -p /c2
mount --bind /c2 /a/b/c1
mount --rbind /a/b /a
And after that container is not dumpable with error:
mnt: Unable to handle mounts under 146:./a
Just because overmounts with shared parent group are prohibited,
but I can't see any problem with enabling them.
https://jira.sw.ru/browse/PSBM-69501
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
What we do before patch:
1) If we are NOT in the same shared group - if we have some parent's
shared group member unmounted, we just wait for it.
2) If we are in the same group - we wait only for members with root
path len shorter than ours.
That is done to make child mount propagate in all shared group,
but I think it is wrong, e.g.:
mkdir -p /dir/a/b/c /d /e /f
mount --bind /dir/a /d
mount --bind /dir/a/b /e
mount --bind /f /e/c
Before c/r we have:
507 114 182:1017985 / / rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
144 507 182:1017985 /dir/a /d rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
146 507 182:1017985 /dir/a/b /e rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
148 146 182:1017985 /f /e/c rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
150 507 182:1017985 /f /dir/a/b/c rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
149 144 182:1017985 /f /d/b/c rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
After c/r we have:
600 132 182:1017985 / / rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
602 600 182:1017985 /f /dir/a/b/c rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
603 600 182:1017985 /dir/a /d rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
604 600 182:1017985 /dir/a/b /e rw,relatime shared:63 master:60 - ext4 /dev/ploop63624p1 rw,data=ordered,balloon_ino=12
There is no propagation as all mounts are in same shared group and
602(150) has shorter root than 603(144) and 604(146).
What we should do:
Wait member of our parent's shared group only if it has our 'sibling'
mount in it. Sibling mount is the one which had propagated to shared
mount of our parent for us when we were mounted. We need to enforce
propagation only for these case.
https://jira.sw.ru/browse/PSBM-69501
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The anonymous shared memory are using shmid for image
name encoding which is unsigned long and we already
met scenario where high bits get strippped off thus
the restore failed.
Lets use unsigned long here, and because pagemap code
is shared between plain memory and anon shared memory
use unsigned long every where.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The index comes from mnt_id which is signed integer
both in kernel and in userspace, but negative value
is never valid, thus don't use it.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For images which are using pid as id for image names
use unsigned format since here is no negative pid
in real system.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Both the kernel and criu uses unsigned int
for it, make the format appropriate.
| struct mount_info {
| ...
| unsigned int s_dev;
| ...
| }
We didn't see negative number here in real life so
I don't think if such %d to %u convention cause
backward compatibility problem ever.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We pass unsigned 4 byte integer here, so
use appropriate format.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Namespace descriptors are not promised to have
constant short names, so just to be on a safe
side.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To test if we can survive with shmid more than 4 bytes
long in image formats.
Without the fix for shmid
| [root@uranus criu] test/zdtm.py run -t zdtm/static/maps01 --fault 132 -f h -k always
| === Run 1/1 ================ zdtm/static/maps01
|
| ========================= Run zdtm/static/maps01 in h ==========================
| Start test
| Test is SUID
| ./maps01 --pidfile=maps01.pid --outfile=maps01.out
| Run criu dump
| Forcing 132 fault
| Run criu restore
| Forcing 132 fault
| =[log]=> dump/zdtm/static/maps01/36/1/restore.log
| ------------------------ grep Error ------------------------
| (00.016464) 37: Opening 0x007f39c04b5000-0x007f3a004b5000 0000000000000000 (101) vma
| (00.016465) 37: Search for 0x007f39c04b5000 shmem 0x10118e915 0x7f97f7ae4ae8/36
| (00.016470) 37: Waiting for the 10118e915 shmem to appear
| (00.016479) 36: No pagemap-shmem-18409749.img image
| (00.016481) 36: Error (criu/shmem.c:559): Can't restore shmem content
| (00.016501) 36: Error (criu/mem.c:1208): `- Can't open vma
| (00.016552) Error (criu/cr-restore.c:2449): Restoring FAILED.
| ------------------------ ERROR OVER ------------------------
And with the fix
| [root@uranus criu] test/zdtm.py run -t zdtm/static/maps01 --fault 132 -f h -k always
| === Run 1/1 ================ zdtm/static/maps01
|
| ========================= Run zdtm/static/maps01 in h ==========================
| Start test
| Test is SUID
| ./maps01 --pidfile=maps01.pid --outfile=maps01.out
| Run criu dump
| Forcing 132 fault
| Run criu restore
| Forcing 132 fault
| Send the 15 signal to 36
| Wait for zdtm/static/maps01(36) to die for 0.100000
| ========================= Test zdtm/static/maps01 PASS =========================
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
flake8 was updated recently and now it shows a few new warnings:
[root@fc24 criu]# make lint
flake8 --config=scripts/flake8.cfg test/zdtm.py
test/zdtm.py:181:4: E722 do not use bare except'
test/zdtm.py:304:2: E722 do not use bare except'
test/zdtm.py:325:3: E722 do not use bare except'
test/zdtm.py:445:3: E722 do not use bare except'
test/zdtm.py:573:4: E722 do not use bare except'
test/zdtm.py:1369:2: E722 do not use bare except'
test/zdtm.py:1385:3: E722 do not use bare except'
test/zdtm.py:1396:2: E722 do not use bare except'
test/zdtm.py:1420:3: E722 do not use bare except'
test/zdtm.py:1820:2: E741 ambiguous variable name 'l'
make: *** [Makefile:369: lint] Error 1
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Also use task_waiter_t syncpoint to make sure fd won't escape
while we're reading output.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
All Jenkins jobs fail with this error:
22:25:13.186: 37: ERR: cgroup_ifpriomap.c:50: Can't mount cgroups (errno = 16 (Device or resource busy))
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
A test to check C/R of multiline cgroup net_prio.ifpriomap.
Before this patches set restoring of this file failed as
it's a multiline cgroup property and kernel can read it
only line-by-line.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Those are devices which are written to devices.allow cgroup.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Skip writing 0 for interfaces, as it's the default value.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
net_prio.ifpriomap property may differ between hosts
as they may have different number of interfaces and this
cgroup property property has init-ns interfaces, not net-ns:
https://www.spinics.net/lists/netdev/msg418785.html
Let's skip fails if interface is no longer present on restore.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
At this moment the kernel doesn't support multi-line write()
to net_prio.ifpriomap. On such write the kernel will parse
only the first line.
That results in the following failed restore:
> (01.454153) cg: Restoring cgroup property value [lo 0
> enp5s0 0
> enp6s0 0
> br0 0
> venet0 0
> host-routed 0
> virbr0 0
> virbr0-nic 0] to [net_prio,net_cls/machine.slice/91d3ac46-380e-4d91-89d3-d2bd1eb30f97/net_prio.ifpriomap]
> (01.454188) Error (criu/cgroup.c:1225): cg: Failed writing lo 0
> enp5s0 0
> enp6s0 0
> br0 0
> venet0 0
> host-routed 0
> virbr0 0
> virbr0-nic 0 to net_prio,net_cls/machine.slice/91d3ac46-380e-4d91-89d3-d2bd1eb30f97/net_prio.ifpriomap: Argument list too long
> (01.472144) Error (criu/cr-restore.c:1013): 20509 killed by signal 9: Killed
> (01.472391) mnt: Switching to new ns to clean ghosts
> (01.472690) Error (criu/cr-restore.c:2007): Restoring FAILED.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As for-cycle already checks it.
While at it - add local CgroupPropEntry variable and use it.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to write some multiline properties line-by-line,
instead of writing all buffer at once - because kernel doesn't
support parsing them in one write().
Previously, it was done for devices.allow list, but I need it
also for netprio.ifpriomap. To make easier reusing this code,
add split_lines parameter to restore_cgroup_prop().
Dropping next_device_entry() and multiply calls to
restore_cgroup_prop() also improves performance: previously
for each property's line, cgroup file was re-open() and close()
again, while new code only calls write() for each line, reducing
number of syscalls done for each line.
This also makes it suitable for future:
if patch(s) for parsing all lines of property with one write()
would be accepted, then we can easily change call to something:
restore_cgroup_prop(&dev_allow, paux, off, !kdat.cgroup_multiline_write);
We can even use split_lines = true by default for all cases,
as strchrnul() will only find zero-terminator as does strlen().
But I don't want to do it - if there are cgroup files which
supportes multi-line write(), it'll add syscalls.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now restore_special_property() only deals which special property
restore and restore_devices_list() deals with devices.list.
BTW, let's have two variables dev_allow and dev_deny on stack
to simplify it - all this fuss with old_val and old_name
kills the fun.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To reduce restore_special_props() size - let's factor a new
function for restoring one special property.
No functional change expected.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For the purpose of separation this as a function, refactor
the code to use local variable prop, so the new function will have
(CgroupPropEntry *) type instead of (CgroupDirEntry *).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's add a function which will tell if cgroup property
is special.
Note that I do not touch restore_special_props() indention
in this patch as I separate subfunction from it in the
next patch, so touching this pile of code once.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As usually -- many bugfixes and several new features. The s390x stuff
goes well too. The most tempting new feature is the ability to dump
and restore files sent over unix sockets (SCM_RIGHTS).
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Its declaration was changed in glibc headers and we don't want
to handle two version of itю
In file included from compel/include/uapi/compel/infect.h:6:0,
from compel/include/uapi/compel/compel.h:12,
from compel/include/log.h:4,
from compel/arch/aarch64/src/lib/infect.c:8:
compel/arch/aarch64/src/lib/infect.c: In function 'sigreturn_prep_regs_plain':
compel/include/uapi/compel/asm/sigframe.h:47:99: error: 'mcontext_t {aka struct <anonymous>}' has no member named '__reserved'; did you mean '__glibc_reserved1'?
#define RT_SIGFRAME_AUX_CONTEXT(rt_sigframe) ((struct aux_context*)&(rt_sigframe)->uc.uc_mcontext.__reserved)
^
compel/include/uapi/compel/asm/sigframe.h:48:41: note: in expansion of macro 'RT_SIGFRAME_AUX_CONTEXT'
#define RT_SIGFRAME_FPU(rt_sigframe) (&RT_SIGFRAME_AUX_CONTEXT(rt_sigframe)->fpsimd)
^~~~~~~~~~~~~~~~~~~~~~~
compel/arch/aarch64/src/lib/infect.c:34:34: note: in expansion of macro 'RT_SIGFRAME_FPU'
struct fpsimd_context *fpsimd = RT_SIGFRAME_FPU(sigframe);
^~~~~~~~~~~~~~~
make[1]: *** [/builddir/build/BUILD/criu-3.5/scripts/nmk/scripts/build.mk:209: compel/arch/aarch64/src/lib/infect.o] Error 1
make: *** [Makefile.compel:36: compel/libcompel.a] Error 2
error: Bad exit status from /var/tmp/rpm-tmp.IExY9K (%build)
This seems to be related to the following glibc changes:
https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=4fa9b3bfe6759c82beb4b043a54a3598ca467289
Reported-by: Adrian Reber <adrian@lisas.de>
Tested-by: Adrian Reber <adrian@lisas.de>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add handeling of R_X86_64_GOTPCRELX and R_X86_64_REX_GOTPCRELX.
They are not that old, so I provided ifdef-guards for them.
According to x86-64 ABI specification paper, they should be
generated instead of R_X86_64_GOTPCREL for cases when relaxation
is possible.
At this moment we can handle them the same way like R_X86_64_GOTPCREL.
[0] https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r249.pdfFixes: #397
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Dmitry Safonov <dima@arista.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
p + FAST_SIZE > buffer + length
In this sentence p + FAST_SIZE may be bigger than (1<<32),
and we will be in trouble.
$ gdb -c coredump test/zdtm/static/write_read01
(gdb) p p
$3 = (uint8_t *) 0xffffa89e
(gdb) p buffer
$4 = (uint8_t *) 0xfff06780
(gdb) p length
$5 = 1000000
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The lazy-thp may fail with older kernels if khugepaded will be fast enough
to merge pages in the partially populated areas.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The CMSG_NXTHDR checks the length of the __next__ cmsg, i.e. the one
that it is about to return for filling. Thus, keeping there anything
but zeroes is unsafe.
Reported-by: Pavel Tikhomirov <snorcht@gmail.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Most of the pieces has already been described in the previous patches :)
so here's the summary.
* Dump:
When receiving a message, also receive any SCM-s (already there) and when
SCM_RIGHTs one is met -- go ahead and just dump received descriptors using
regular code, but taking current as the victim task.
Few words about file paths resolution -- since we do dump path-ed files
by receiving them from victim's parasite, such files sent via sockets
should still work OK, as we still receive them, just from another socket.
Several problems here:
1. Unix sockets sent via unix sockets form knots. Not supported.
2. Eventpolls sent via unix might themseves poll unix sockets. Knots
again. Not supported either.
* Restore:
On restore we need to make unix socket wait for the soon-to-be-scm-sent
descriptors to get restored, so we need to find them, then put a dependency.
After that, the fake fdinfo entry is attached to the respective file
descs, when sent the respective descriptors are closed.
https://github.com/xemul/criu/issues/251
v2: Addressed comments from Kirill
* Moved prepare_scms before adding fake fles (with comment)
* Add scm-only fles as fake, thus removing close_scm_fds
* Try hard finding any suitable fle to use as scm one when
queuing them for unix socket scm list, only allocate a new
one if really needed
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In order to make sender of a descriptor (unix socket) be restored
_after_ the descriptor in question, we need to find out those
sockets early (before post-prep calls).
The problem is that current code gives us info about who's the
queuer for who only in post-prep hooks, so the peer resolution
should happen right in collect callback.
At the same time we need to make sure that all peers configured
in the image exist, as well as need to put master/slave flags
for socketpairs. Both these actions can only happen in post-prep.
Said that -- the current peer resolve routine should be split
into two steps.
v2: Handle the socket connected to self (dgram)
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The sk-queue.img keeps socket IDs as recepient descriptor. For
SCM code we'll need to find the unix sk info who is the sender
for a particular other socket by this ID. There's already the
queuer field in the unix_sk_info, but it needs to be an ID
rather than inode. Fortunately, id-inode pairs are unique.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For SCM restore we need to know all queuers, even if they are
socketpair-s, but current code skips this setting for one
half of them. So set this info for every socket out there.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In SCM code there will be the need to attach a newly created
FdinfoEntry to a particulat file desc object, then get the
created fdinfo helper object back.
Current code only allows this via two lookup calls -- first
one to attach entry to desc by ID (lookup #1), then get the
fdinfo helper by FD (lookup #2).
Fortunately, the exising code allows simple split that gives
us the optimized routine.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In SCM patch we'll need to generate temporary fdinfo entry
for a task that will send descriptors via sockets. Sometimes
the files in questions will NOT have any other fdinfo-s (if
they are SCM-sent and closed), so we need a helper that
would either give us existing fdinfo or say there's no such.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
An aux code to dump the received file and report back its
ID and type.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Actually all file-s we dump have unique IDs, regardless of
their types. This fact will be used to reduce complexity
of the SCM code -- instead of keeping TYPE:ID pair it'll
save only the ID.
Siad that -- we will need the way to lookup desc by ID only.
v2: Older images had fifo-s and tty-s having matching IDs
with respective reg-file entries
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To support SCMs we'll need to receive them into criu task
(see the SCM patch for details), then dump the received
file as if it was in the dumpee. Then the info about received
descriptor will be written into packet entry.
For this we'll need to perform all the regular file dumping
code BUT not write the FdinfoEntry into image, so shuffle
the code for that.
The gist of the patch is in two changes -- one in the
do_dump_gen_file(), the other in dump_task_files_seized().
The rest is just tossing the arguments of the functions
relevant to that change.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Same thing as for fifo-s.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The plan is to have all file entries have unique ID. Fifo
generates a reg file entry to reuse the whole reg-files
c/r-ing engine (ghosts, open-by-path, etc.) and right now
ID for this entry is the same as for fifo entry.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
SCM-dumping code won't provide the ctl for TTY dump. To
make this work we'll have to peek required tty info from
current (see the SCM patch), but I doubt that anyone
sends TTYs via sockets ... so keep this in TODO list.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Only the send code is altered, as upon receiving kernel
merges all scm_rights int one. CRIU relies on this merge
and this is to catch situations if the kernel suddenly
stops doing this.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This will be used in further to determine whether task's namespace
allows to restore file_desc.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Keep int pid with short-len fields to avoid
alignment gaps in structure.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The algorhythm of searching file master will be more complicated
in next patches. So, move current functionality in separate func.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The only user is fifo, but it uses collect_fd()
to do read only actions (the only change is
fifo_info::reg_d population, which may be easily
moved to open_fifo_fd()).
So, move the collect_special_file() functionality
from collect_fifo_fd() to open_fifo_fd() and
kill collect_fd method at all.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Declare it extern and allow to use outside files.c.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On 01.06.2017 14:34, Kirill Tkhai wrote:
> Everything is prepared: the pair "type and id" is
> uniqul, so find_file_desc() in collect_fd() will
> work as expected and it will find the file_desc
> we just added in autofs_create_pipe()->collect_one_pipe_ops().
>
> So, the not-generic helper may be killed.
>
> Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Returned debug print:
[PATCH 4/5 v2]files: Kill autofs_create_fle() and use generic helper
Everything is prepared: the pair "type and id" is
uniqul, so find_file_desc() in collect_fd() will
work as expected and it will find the file_desc
we just added in autofs_create_pipe()->collect_one_pipe_ops().
So, the not-generic helper may be killed.
v2: Leave debug print on the place.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Acked-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Acked-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
shmalloc() already returns address with sizeof(unsigned long)
alignment. So, the second alignment is useless.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Allow to mark some fles as "fake" and close them, when they are not needed.
v2: Cache fake file in separate list, when they are restored,
to do not iterate over files list again.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It has only one user. Also, in next patches will be
used pstree_item_by_virt() function, and I don't
want to add "#include" to "files.h" for it, and to
nest headers.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Fake masters are files, which are not owned by
a process, that is able to open them.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Due to a misprint in an if the 6rd info for sit device
was restored when not present.
https://github.com/xemul/criu/issues/366
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Same here -- prepare the IFLA_INFO_DATA section using the
date from SitEntry.
Issue #11
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Nothing special here, just parse all known NLAs and keep them
on the image.
Issue #11
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
page_ids is a global variable and it is used to dump shared memroy,
process memory and ipc shared memory.
The problem is that an IPC namespace is dumped in a child process,
so page_ids isn't changed in a parent process. This patch is a quick
workaround this issue.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently test_daemon() sends a signal to a parent process,
when a test completed a prepartion stage. But it doesn't work,
if a child changed uid and gid, because it doesn't have enough
permissions in this case.
This patch reworks a synchronization scheme to use a futex
instead of sending signals.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Wait for thread to finish its creation instead of
calling sleep. Same time call for test_daemon
only when we're ready.
CC: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For us it doesn't matter what names of users and groups are used,
we want to be sure that we restore right uid-s and gid-s.
If we use these functions, we can't run tests in namespaces and
they use an external unix socket, what can be a problem too.
sk unix: Runaway socket: ino 0x1df1ae4 peer_ino 0x1df1ae3 family 1 type 1 state 1 name /run/dbus/system_bus_socket
Error (criu/sk-unix.c:712): sk unix: External socket is used. Consider using --ext-unix-sk option.
Cc: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
so that .gcda (coverage data) files are created with read-write
permissions for all, otherwise uns tests will not be able to
modify these files and code coverage data will not be collected
for them.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If a connection was reseted, it can have some data in a sent queue,
a use can't read this data, so we can ignore them too.
https://jira.sw.ru/browse/PSBM-67026
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- Add new test "s390x_runtime_instr" to check if the RI control block is
correctly restored when the RI is active.
- Add RI control block in test s390x_regs_check.c
The original test case for RI has been provided by
Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- Add new test "s390x_gs_threads" for GS with broadcast command for the
s390_guarded_storage() system call.
- Add GS control blocks in test s390x_regs_check.c
The original test case for GS has been provided by
Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Dump and restore process with RI control block. Runtime instrumentation
allows to collect information about program execution as CPU data.
The RI control block is dumped and restored for all threads.
Ptrace kernel interface is provided by:
c122bc239b13 ("s390/ptrace: add runtime instrumention register get/set")
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Dump and restore tasks with GS control blocks. Guarded-storage is a new
s390 feature to improve garbage collecting languages like Java.
There are two control blocks in the CPU:
- GS control block
- GS broadcast control block
Both control blocks have to be dumped and restored for all threads.
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add new function arch_set_task_regs_nosigrt(). It allows to restore
architecture-specific registers not present in sigreturn signal frame.
Each architecture can overwrite this function.
The arch_set_task_regs_nosigrt function restores the registers between the
final sigreturn and PTRACE_DETACH. We do this at this point because
we are sure that all threads have already been created.
Add arch_set_thread_regs in pre-dump because some registers may have
been changed by the parasite infection and they are not present in
sigreturn signal frame.
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Running all the tests with --lazy-pages and --remote-lazy-pages takes too
long. Let's run only several representing tests for those cases.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The UFFDIO_UNREGISTER returns ENOMEM only when it is unable to get
mm_struct. We can assume in such case that the task is exited.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On Fedora rawhide with kernel-headers-4.14.0-0.rc2.git0.1.fc28.x86_64
glibc-devel-2.26.90-15.fc28.x86_64 criu does not build any more:
In file included from /usr/include/linux/aio_abi.h:31:0,
from criu/cr-check.c:24:
/usr/include/sys/mount.h:35:3: error: expected identifier before numeric constant
MS_RDONLY = 1, /* Mount read-only. */
^
make[2]: *** [/builddir/build/BUILD/criu-3.5/scripts/nmk/scripts/build.mk:111: criu/cr-check.o] Error 1
make[1]: *** [criu/Makefile:73: criu/built-in.o] Error 2
make: *** [Makefile:233: criu] Error 2
This simple re-ordering of includes fixes it for me.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise we will see warnings like these ones:
Warn (criu/kerndat.c:805): Can't load /run/criu.kdat
Warn (criu/net.c:2726): Unable to get a socket network namespace
Warn (criu/kerndat.c:844): Can't keep kdat cache on non-tempfs
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
test/zdtm.py:1535:30: E711 comparison to None should be 'if cond is not None:'
test/zdtm.py:1538:31: E711 comparison to None should be 'if cond is not None:'
test/zdtm.py:1601:31: E711 comparison to None should be 'if cond is not None:'
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As requested, implement a test with two threads that have mismatching,
non-root credentials, like Apache does.
Signed-off-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We are carrying uids/gids in per-thread way since v1.8,
so no need to require them to match anymore. We still
require seccomp to match though. Need to revisit, seems
may relax this requirement as well.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When checkpoint is done on the kernels where
commit 6933599697c96c3213c95f5f1fc7cb6abfd08c54
is not yet present then mask is not filtered
and saved in image in this raw form.
For such case restore on more modern kernels
will fail because only a small set of events
are allowed to pass from userspace.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We found a good plugin for Jenkins to analize test results,
but it can handle only the junit format.
v2: work without the junit python module
v3: install junit-xml, because zdtm.py is executed
with the --report option from jenkins scripts.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It isn't required and it is absant on alpine
autofs.c:9:25: fatal error: bits/signum.h: No such file or directory
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
(00.052683) Error (soccr/soccr.c:166): Failed to obtain TCP_INFO: No error information
We don't need a whole tcp info, so get only a part
what we are going to use.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise we get errors like this:
/usr/include/sys/socket.h:315:5: note: expected 'const struct sockaddr *' but argument is of type 'struct sockaddr_un *'
int bind (int, const struct sockaddr *, socklen_t);
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In file included from socket_listen.c:22:0:
/usr/include/wait.h:1:2: error: #warning redirecting incorrect #include <wait.h> to <sys/wait.h> [-Werror=cpp]
#warning redirecting incorrect #include <wait.h> to <sys/wait.h>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The x86_64 job is the one we run inside Docker (as opposed to 'local',
which runs on the host). Let's update this to use Ubuntu Zesty, and
since it has clang-4 (unlike the 'local' one) it makes sense to add
a clang build.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Also, use more official / better maintained Docker image repo.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With clang 4, the following error appears:
> CC criu/pie/parasite.o
> In file included from criu/pie/parasite.c:23:
> criu/arch/arm/include/asm/parasite.h:6:21: error: this function
> declaration is not a
> prototype [-Werror,-Wstrict-prototypes]
> *ptls = ((tls_t (*)())0xffff0fe0)();
> ^
> void
> 1 error generated.
Apparently, adding void fixes it.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Numerous improvement to extract-deb-pkg, in no particular order:
* Use bash
* More strict error checking (set -u -o pipefail)
* Print error message if target dir exists
* Check number of arguments, provide usage info
* Separate mirror to a variable for easier changing
* Use mirrors.kernel.org
* Use https and check cert with curl
* Make curl silent
* Use zgrep instead of gunzip | grep
* Error out with a message in case more than 1 package was found
* Do not create a target directory before we need it
* Fix shellcheck warnings (way too many to mention)
* ...
* PROFIT!!!111
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This comes with newer libc headers so we can catch errors earlier.
Also, clang 4.0.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's use Ubuntu 17.04 "Zesty" for ARM-64 bit CI.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Same as commit e4000c59a7 ("Dockerfiles: don't ignore make failures").
Seems that Dockerfile.fedora-asan copy/pasted an old version.
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is what we have:
> compel/src/lib/infect.c:1145:38: error: taking address of packed member
> 'uc_sigmask' of class or structure 'ucontext_ia32' may result in an
> unaligned pointer value [-Werror,-Waddress-of-packed-member]
> blk_sigset = RT_SIGFRAME_UC_SIGMASK(f);
> ~~~~~~~~~~~~~~~~~~~~~~~^~
> compel/include/uapi/asm/sigframe.h:133:4: note: expanded from macro
> 'RT_SIGFRAME_UC_SIGMASK'
> (&rt_sigframe->compat.uc.uc_sigmask))
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 1 error generated.
Indeed this results in an unaligned pointer, but as this is intended and
well known (see commit dd6736bd "compel/x86/compat: pack ucontext_ia32"),
we need to silence the warning here.
For more details, see https://reviews.llvm.org/D20561
Originally found by Travis on Alpine Linux, reproduced on Ubuntu 17.10.
[v2: fix for non-x86]
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For older kernels (e.g. RHEL7 with 3.10) it seems that wait(NULL) after
ptrace(PTHREAD_ATTACH) does not work properly for threads that have
to be created via clone().
Fix this by using waitpid() with the __WALL flag.
>From the waitpid() man page:
__WALL (since Linux 2.4)
Wait for all children, regardless of type ("clone" or "non-clone").
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Plus patch replaces atoi(32 bit) to xatol(64 bits) for "pipe_ino" mount
option thus fixing the issue with negative inode number for big values.
v2: fixed uninitialized "err" variable in "parse_options" function
Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
These helpers are safe versions of atol() and atoi() respectively.
And they check for overflow and NAN errors
v3:
1) Added string print to convertion error message in xatol_base()
2) Added check for INT range in xatoi()
Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
==36==ERROR: AddressSanitizer: heap-buffer-overflow on address
0x60200000001c at pc 0x7fb26c88d5f9 bp 0x7ffc15087d40 sp 0x7ffc150874d0
WRITE of size 13 at 0x60200000001c thread T0
#0 0x7fb26c88d5f8 in vsprintf (/lib64/libasan.so.4+0x9e5f8)
#1 0x7fb26c88d986 in __interceptor_sprintf (/lib64/libasan.so.4+0x9e986)
#2 0x402453 in main /root/git/main/criu/test/zdtm/static/chroot.c:68
#3 0x7fb26c43e4d9 in __libc_start_main (/lib64/libc.so.6+0x204d9)
#4 0x4031b9 in _start (/root/git/main/criu/test/zdtm/static/chroot+0x4031b9)
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Without this message, we don't know which fdinfo can't be opened.
https://github.com/xemul/criu/issues/390
Signed-off-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On VZ7 we have a problem in random tests on iptables restore when
running tests in parallel(one iptables-restore instance tries to lock
xtables lock and fails while other instance(some iptables* command) is
already holding the lock):
================== Run zdtm/static/socket_udp_shutdown in ns ===================
Start test
./socket_udp_shutdown --pidfile=socket_udp_shutdown.pid --outfile=socket_udp_shutdown.out
Run criu dump
Run criu restore
=[log]=> dump/zdtm/static/socket_udp_shutdown/77/1/restore.log
------------------------ grep Error ------------------------
(00.158864) 1: Running ip rule delete table local
(00.167319) 1: Running ip rule restore
(00.175647) 1: Running iptables-restore for iptables-restore
Another app is currently holding the xtables lock. Perhaps you want to use the -w option?
(00.185245) 1: Error (criu/util.c:719): exited, status=4
(00.185289) 1: Error (criu/net.c:1739): iptables-restore failed
(00.185301) 1: Error (criu/net.c:2382): Can't create net_ns
(00.185370) 1: Error (criu/util.c:1412): Can't wait or bad status: errno=0, status=65280(00.187281) Error (criu/mount.c:2944): mnt: Can't remove the directory /tmp/.criu.mntns.Ai5EG9: No such file or directory
(00.187298) uns: calling exit_usernsd (-1, 1)
(00.187344) uns: daemon calls 0x466a40 (93, -1, 1)
(00.187361) uns: `- daemon exits w/ 0
(00.188375) uns: daemon stopped
(00.188390) Error (criu/cr-restore.c:2450): Restoring FAILED.
------------------------ ERROR OVER ------------------------
Test zdtm/static/socket_udp_shutdown FAIL at CRIU restore
https://ci.openvz.org/job/CRIU/job/CRIU-virtuozzo/job/criu-dev/2873
It happens now in every test-suit run on VZ7 host as we had updated to
1.4.21-18 iptables package, which has patches for xlocks support in
iptables-restore ported:
* Mon Apr 24 2017 Thomas Woerner <twoerner@redhat.com> 1.4.21-18 - Add
support for --wait options to restore commands (RHBZ#1438597)
Whether these patches are ported to other distribution packages we'll
have these problem in other distributions.
Just add -w to wait lock on iptables-restore as older versions does not
error on invalid option, just warning is printed.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
New ip[6]tables-restore utils has this parameter,
which allows to wait for xtables lock, if it's
occupied. When they don't wait, then the restore
of iptables fails.
Old versions just ignore this parameter
with error in stderr, but it does not make them
fail. So, pass it unconditionally.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The errors set by both uffdio_copy and uffdio_zeropage are the same and
require the same handling. Let's use a helper function to handle the errors
returned by uffdio_copy and uffdio_zero.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When running 'make zdtm' on s390x it fails on RHEL7 with:
make[3]: Leaving directory `/tmp/criu/test/zdtm/lib'
CC s390x_regs_check.o
s390x_regs_check.c: In function "util_hexdump_grp":
s390x_regs_check.c:214:7: error: "ptr" may be used uninitialized
in this function [-Werror=maybe-uninitialized]
ptr += sprintf(ptr, "%02x", buf[i]);
Fix this and assign ptr from the beginning to help gcc.
Reported-by: Adrian Reber <adrian@lisas.de>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The origin idea was to set --empty net for criu dump and criu restore,
but before cde33dcb06 ("empty-ns: Don't C/R iptables too (v2)"),
criu restore worked without --empty net and we didn't notice that
docker doesn't set this option on restore.
After a small brainstorm, we decided that it is better to remove
this requirement. Docker has to set this option, but with this changes,
the docker issue will be less urgent.
https://github.com/checkpoint-restore/criu/issues/393
So, the long-running task with lazy restore is (almost) finished :) Some
issues are still to be resolved, but the heaviest lift has been done.
Another notable thing is VDSO C/R rework. It's now more robust and fast.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When merging files into one image we've forgotten about crit x
feature that scans image files by names.
https://github.com/xemul/criu/issues/381
The patch was made for master (as in criu-dev there was problem
with pstree_item.pid parsing), but should apply to dev smoothly.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When an error occurs we need to close a file descriptor and unmap a region.
Use a separate label for each cleanup.
Fix CID 182644 (#1-2 of 2): Use after close (USE_AFTER_FREE)8. pass_closed_arg:
Passing closed handle f.fd as an argument to bclose
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It's not really interesting and just pollutes the log
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The intention was to make sure, that only one packet is sent at a time.
And thus read has to return exactly the size of one packet.
But it doesnt' work as expected, because size of autofs_v5_packet_union
differs on 32 bit and 64 bit architectures.
This is a bug, but it's hidden so deeply, that no one really cares by the
following 2 aspects:
1) Autofs pipe has O_DIRECT flag, which means excess bytes will be discarded
upon read.
2) No one tries to read more than one packet size at a time.
So let's fix the test instead and do not try to read more bytes, than
expected.
Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't need to look up a mount info element, because
we already have it there.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
That's a merge conflict between vdso patches set and s390 set.
Cc: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Cc: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We can save some syscalls for *each* dumpee if we don't
open()/seek()/read()/close() /proc/pid/pagemap for each
dumpee and even don't use parasite to parse symtable if
pagemap is unavailable.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If it does preserve, we can omit checking pagemap for dumpee or
filling symtable in parasite.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Just map vdso at restorer's parking zone, no need for
searching it in CRIU and remap it to park zone.
That will save some open()/read()/close() syscalls
for parsing maps file.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If there is no vdso in images - we don't need to map it.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Test for previously fixed bugs for vdso-trampolines insertion:
- unmapping original vvar (which went unnoticed)
- leaving rt-vvar after each C/R cycle and resulting pollution
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's hard to stop, when you've begun.
No functional change is expected.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As rt-vvar can be placed lower (by address) than rt-vdso,
it likely will go earlier in vma_area_list.
That means that at the moment, when we've found rt-vdso,
we already passed rt-vvar and rt_vvar_marked pointer
will not be initialized.
Search for rt-vvar during the second vma list traverse,
so we will always find it if it's present.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I think, it's better if we still restore the original vvar
as some code may expect vma to be there or may dereference
pointer there.
E.g., if we checkpointed task while it was on vdso page,
it'll dereference pointer to vvar. Better keep it in vmas.
So, the original code deleted it becase it was proxy_vvar_marked,
which I think is misnaming problem.
Having two vvar addresses named rt_ and orig_ describes what to
do with them on dump.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to place @rt_vvar_addr into vdso mark, as we don't know
the position of rt-vvar to be dropped on the following dumps.
I've renamed proxy_*_addr to orig_*_addr, as it looks more
describing.
orig_*_addr we need for marking those VMAs as accordingly,
so restorer would know what to do with them. Otherwise, it'll
think they are just regular vmas.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Previously, arch_prctl(ARCH_MAP_VDSO_32) was only used by
CONFIG_COMPAT to map compatible vdso blob for 32-bit restoree.
But we can make it more generic:
Omitting mremap() for moving vdso to rt-vdso zone in restorer
and afterward on needed position in restoree.
Also omitting reading /proc/self/maps to find vdso/vvar
addresses (to park afterward in restorer).
TLDR; under this kdat feature we can get rid of a buch of mremap()'s
for each restoree and from parsing /proc/self/maps in vdso_init_restore().
The API is present from v4.9 kernel.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Found with fault-injected jump trampolines in vdso,
that on ia32 tests rt-vdso got unmapped.
I've fixed it previously, but have forgot it during
debugging vdso cleanup.
Fixes: commit 8544895a52 ("ia32/restorer: move 32-bit pie unmap to x86")
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I'll need to modify it - make it small and ready for changes.
No functional change is expected.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Make it more readable and change-ready.
No functional change is expected.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is just to split this oversized outgrowed plumped up
parasite_fixup_vdso() and separate it logically.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Generalize addr-to-pfn conversion in one function.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Expand vaddr_to_pfn() so it can read and translate to PFN
from already opened fd. This can be used as optimization
if one need to translate a couple of addresses and
also to read other task's PFN.
I'll use it in the next patch for reading other tasks's
vdso's PFN.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's hide those kernel details in enum.
Further in this patches set I'll add kdat test for presence
of "[vdso]" hint after mremap(), so we will skip any checking
on kernels > v3.16 and do not init vdso_pfn also
(skipping parsing of self-pagemap).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On s390 we don't use vvar. Therefore vvar_size in not been initialized
and the value remains VVAR_BAD_SIZE.
Fix the BUG() statement to also cover this case.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In file included from criu/include/util-vdso.h:23:0,
from criu/include/kerndat.h:8,
from criu/lsm.c:8:
criu/arch/aarch64/include/asm/vdso.h:17:35: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'aarch_vdso_symbol1'
static const char* __maybe_unused aarch_vdso_symbol1 = "__kernel_clock_getres";
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Don't need to parse vdso symtable each restore - it's boot-persistent,
so move it into criu.kdat file on tmpfs.
That will also remove syscalls made for filling compat vdso symtable
by compat vdso helper.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On dump we only need vdso_pfn to be filled,
on restore we need filled symtables.
That means, that we can omit filling symtables on dump,
which also means no need in calling compat_vdso_helper
process with fork(), pipe(), read(), write() and so on syscalls.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As ASLR randomizes {vdso,vvar}_start between criu launches,
vdso_parse_maps() should be called each launch:
- on restore to know {vdso,vvar}_start position for later parking
in restorer's save zone
- on checkpointing to get vdso's pfn for pre-v3.16 kernels
which lose "[vdso]" hint in maps file.
But vdso_fill_symtable() call may be omitted if symtable is
inside kdat file.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Preparation for saving vdso_symtable in kdat, which will
allow skip parsing of native and compat symtables - that
at least will save from running compat helper each criu launch.
As {vvar,vdso}_start are randomized with ASLR, there is no
point in saving them into kdat. We'll still need to reread
them from /proc/self/maps for awhile.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I plan to keep boot-persistent vdso_symtable inside kdat,
moving {vvar,vdso}_start addresses out into new structure.
As order of vdso/vvar is preserved across one booting store
it inside of vdso_symtable.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Make a function which decides if we need to insert
jump trampolines, or if the blobs are equal and just a remap
if enough.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Ordering check for vvar/vdso blobs was introduced with
the commit b00bdb2dbc ("vdso: x86 -- Test VMAs order in vdso_proxify")
Let's simplify it to more readable version.
As above we've compared that vvar/vdso's blob size from dumpee matches
sizes of rt-vvar/rt-vdso, kill that xor here.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Check that task without vvar & vdso blobs is restored without them.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's just unmap criu's vdso & vvar if restoree doesn't
have them.
This could be fired e.g. by migrating task from vdso-disabled
kernel to vdso-enabled one.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The plan is to keep boot-persistent vdso properties in symtable,
to omit parsing it in each invocation of criu.
As sizes of vdso/vvar are being stable on the same kernel,
move them into symtable, substituting end addresses.
Begin/end addresses are randomized by ASLR so there is no point
in storing them in kdat.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The right order for all of our 4 archs is:
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
int __user *, parent_tidptr,
unsigned long, tls,
int __user *, child_tidptr)
See Linux kernel for the details.
Note, this is just a fix, and it's not connected with the second patch.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The check_features RPC function required that both known fields are
present. Without those fields it exited with an error. If RPC users
where not specifying all parameters it would fail. It should, however,
be possible to only check for a subset of options.
Each supported option is checked separately anyway in the forked criu
which does the actual check.
Removing the check also enables RPC clients with older protobuf
definitions to use the feature check.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The recent changes to user address space limits in the Linux kernel break
the assumption that TASK_SIZE is 128TB. For now, the maximal task size on
ppc64le is 512TB and we need to detect it in runtime for compatibility with
older kernels.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Even with 2 parallel jobs maps04 takes too much time with
--remote-lazy-pages. Let's skip it for now.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If there were fork()'s during lazy-restore we create a shallow copy of the
parent process' page-read. Since all the copies reference the same open
files, we cannot close the page-read until we finish restore of all the
processes that share the page-read.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Running zdtm/static/maps04 with --remote-lazy-pages in parallel with 3
other tests takes too much time on the Jenkins builder. Let's try running
with --parallel 2.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When there is a stale kdat cache file it's contents is read into the memory
and we end up requesting random userfaultfd features. Explicitly set the
kdat.uffd_features to zero before querying the kernel resolves the issue.
✓ travis-ci: success for kerndat: set uffd features to 0 before querying kernel
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Without non-cooperative userfaultfd some programs may fail during lazy
restore because they perform operations that cannot be handled by the
lazy-pages daemon.
✓ travis-ci: success for lazy-pages: update checks for availability of userfaultfd (rev3)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The kerndat_init() is now called before the jump to action handler. This
allows us to directly use kdat without calling to the corresponding
kerndat_*() methods.
✓ travis-ci: success for lazy-pages: update checks for availability of userfaultfd (rev3)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
After the commit
02c763939c10 ("test/zdtm: unify common code")
CFLAGS with -D_GNU_SOURCE defined in the top Makefile
are being passed to tests Makefiles.
As _GNU_SOURCE is also defined by tests, that resulted in
zdtm tests build failures:
make[2]: Entering directory `/home/criu/test/zdtm/lib'
CC test.o
test.c:1:0: error: "_GNU_SOURCE" redefined [-Werror]
#define _GNU_SOURCE
^
<command-line>:0:0: note: this is the location of the previous definition
cc1: all warnings being treated as errors
make[2]: *** [test.o] Error 1
However, we didn't catch this in time by Travis-CI, as zdtm.py doesn't
do `make zdtm`, rather it does `make -C test/zdtm/{lib,static,transition}`.
By calling middle makefile this way, it doesn't have _GNU_SOURCE in
CFLAGS from top-Makefile.
I think the right thing to do here - is following CRIU's way:
rely on definition of _GNU_SOURCE by Makefiles.
This patch is almost fully generated with
find test/zdtm/ -name '*.c' -type f \
-exec sed -i '/define _GNU_SOURCE/{n;/^$/d;}' '{}' \; \
-exec sed -i '/define _GNU_SOURCE/d' '{}' \;
With an exception for adding -D_GNU_SOURCE in tests Makefile.inc for
keeping the same behaviour for zdtm.py.
Also changed utsname.c to use utsname::domainname, rather private
utsname::__domainname, as now it's uncovered (from sys/utsname.h):
> struct utsname
> {
...
> # ifdef __USE_GNU
> char domainname[_UTSNAME_DOMAIN_LENGTH];
> # else
> char __domainname[_UTSNAME_DOMAIN_LENGTH];
> # endif
Reported-by: Adrian Reber <areber@redhat.com>
Cc: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With kdat cache and unified kerndat_init() we can call it very early in
crtools and then kdat information will be available for all cr-* actions.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
kdat and lazy-pages use nearly the same sequence to open userfault. This
code can definitely live in a dedicated function.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Raise an exception for kernels that do not have userfaultfd. For the
kernels that have userfaultfd but do not provide non-cooperative events
(4.3 - 4.11) just print a warning.
Fixes: #363
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
For the older kernels the implementation of userfaultfd would not include
non-cooperative mode. In such case it is still possible to use uffd and
enable lazy-pages, but if the restored process will change its virtual
memory layout during restore, we'll get memory corruption.
After this change 'criu check --feature uffd' will report success if the kernel
supports userfaultfd at all and 'criu check --feature uffd-noncoop' will
report success if the kernel supports non-cooperative userfaultfd.
Suggested-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
All the iovecs in uffd.c are lazy, there is no point in having _lazy_ in
functions that operate on these iovecs.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There's no real point to have two-liner wrapper for compete_page_fault and
uffd_io_complete is better semantically.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Both test seem to reproduce issue #357 [1] too frequently which make it
really annoying. Temporarily remove them from lazy-pages passes until the
issue is fixed.
[1] https://github.com/xemul/criu/issues/357
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The page_pipe_read obsoleted page_pipe_split and related functions and
there is no point in keeping them.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When page-server gets a request for an absent pagemap from lazy-pages
daemon, it should not reply with "zero pages"'.
The pagemap should be completely in sync between src and dst and dst
should never request pages that are not present. Maybe we should return
-1 here? At least we'll have a chance that dump will unroll everything...
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Make it call .write_pagemap once and decide whether or not to
call .write_pages based on the flags caluculated in one place
as well.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Same thing for the boolean value saying whether or not to send
lazy pagemaps alone or follow them with the respective pages.
This value is non-true in the single place, so let's simplify
the API and keep this bool on xfer object.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The offset in question is used by shmem dumping code to dump
memory segments relative to shmem segment start, no to task
mapping start. The offset value is now the part of the xfer
callback and is typically 0 :) Let's keep this on xfer object
to simplify the xfer API.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are two places left that send ps_iov by hands into
socket. Switch it to use common helper.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are cases when we need to specify flags with which
to send the ps_iov, so tune-up the send_psi for that and
use where needed.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The only thing it does is puts 4 values on the on-stack ps_iov,
let's avoid double stack copying and put the values on ps_iov
in callers.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Introduce the PS_IOV_ADD_F command that is to add pages with
flags. We already use the similar notation on page-xfer -- the
single write callback with pagemap and flags. For page-server
let's use the same. Legacy _HOLE and _PAGE handling is kept.
Changed commands numbers are OK, as the commands in question
are still in criu-dev branch.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The page_read.seek_pagemap already tunes the pages offset,
so the separate call for skip_pagemap_pages in the routine
in question is always no-op.
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When the remap 'from' parameter matches an IOV end we try to split that IOV
exactly at its end and effectively create an IOV with zero length.
With the off-by-one fix we will skip the IOV in such case as expected.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we combine pre-dump with lazy pages, we populate a part of a memory
region with data that was saved during the pre-dump. Afterwards, the
region is registered with userfaultfd and we expect to get page faults for
the parts of the region that were not yet populated. However, khugepaged
collapses the pages and the page faults we would expect do not occur.
To mitigate this problem we temporarily disable THP for the restored
process, up to the point when we register all the memory regions with
userfaultfd.
https://lists.openvz.org/pipermail/criu/2017-May/037728.html
Reported-by: Adrian Reber <areber@redhat.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The PR_SET_THP_DISABLE prctl allows control of transparent huge pages on
per-process basis. It is available since Linux 3.15, but until recently it
set VM_NOHUGEPAGE for all VMAs created after prctl() call, which prevents
proper restore for combination of pre- and post-copy. A recent change to
prctl(PR_SET_THP_DISABLE) behavior eliminates the use of per-VMA flags and
we can use the new version of the prctl() to disable THP.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The is_vma_range_fmt and parse_vmflags will be required for detection of
availability of PR_SET_THP_DISABLE prctl
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now we have two separate recv-calling routines, that receive
header and pages from page-server. These two can finally be
unified.
After this the sync-read code looks like -- start async one
and wait for it to finish right at once.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is prerequisite for the next patch.
v2: spellchecks, code reshuffle
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now these two look exactly the same and we can have
only one call with additional sync/async (flags) arg.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The newly introduced sync-read call may look exactly
the same as its async pair by using the respective
complete callback.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There's no need in two API calls to read xfer header
and pages themselves, so merge them into one single
call.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
* drop --keep-going etc from --lazy-pages pass
* add --remote-lazy-pages pass
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
* select excluded tests based on the kernel version
* test local and remote lazy-pages with and withour pre-dump
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The page-read for child process is a shallow copy of the parent process
page-read. They share the open file descriptors and the pagemap.
The lpi_fini of the child processes should not release any resources, they
all will be released during lpi_fini of the parent process.
Fixes: #325
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For the remote lazy pages case, to access pages in the middle of a pipe we
are splitting the page_pipe_buffers and iovecs and use splice() to move the
data between the underlying pipes. After the splits we get page_pipe_buffer
with single iovec that can be used to splice() the data further into the
socket.
This patch replaces the splitting and splicing with use of a helper pipe
and tee(). We tee() the pages from beginning of the pipe up to the last
requested page into a helper pipe, sink the unneeded head part into
/dev/null and we get the requested pages ready for splice() into the
socket.
This allows lazy-pages daemon to request the same page several time, which
is required to properly support fork() after the restore.
As added bonus we simplify the code and reduce amount of pipes that live in
the system.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Until now once we've started to fetch an iovec we've been waiting until
it's completely copied before returning to event processing loop. Now we
can have several request for the remote pages in flight.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There could be several outstaning requests for the same page, either from
page fault handler or from handle_remaining_pages. Verifying that the
faulting address is already requested is not enough. We need to check if
there any request in flight that covers the faulting address.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
v2: When uffd is present, the reported features may still be 0,
so we need one more bool for uffd syscall itself.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
They still will fail with --remote-lazy-pages, so mark them as
'noremotelazy'
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This allows skipping tests that are not yet run with --remote-lazy-pages,
but can be run with --lazy-pages
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When running with --lazy-pages or --remote-lazy-pages, the daemons should
run in the background, rather than complete before t.stop() is called.
Many tests try to verify things are ok after test_waitsig() and that's
exactly the place where they access memory and cause page faults.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Most of zdtm test should pass with --lazy-pages with kernels newer than
4.11.
Some test excluded for older kernels surprisingly pass even now, mainly
becuase they do not actually stress userfaultfd, which will be fixed in the
upcoming commits :)
The cmdlinenv00 fails even with kernel 4.11 because of a race between uffd
and gup in the case external process reads /proc/<pid>/cmdline before
memory containing the command line is populated.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the version from v4.11-rc5. Apparently, that would be the userfault
ABI for the next few month.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The UFFDIO_EVENT_EXIT didn't make it upstream because of possible races in
exit() syscall [1].
The only way to detect that the monitored process is exited is checking for
ENOSPC errno value set by uffdio_copy.
[1] http://www.spinics.net/lists/linux-mm/msg122467.html
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We only use one epoll instance to manage lazy-pages related I/O. Making
epollfd file-visible will allow cleaner implementation of the restored
process exit() calls tracking.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Both lazy_iov and lp_req have two fields for address/start: the run-time
address that tracks remaps, and the "dump time" address, which is required
for pagemap accesses.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The lazy-pages daemon have to properly track changes to virtual memory
layout of the restored process. The test verifies that lazy-pages daemon
properly reacts to fork(), exit(), madvise(MADV_DONTNEED) and mremap()
events.
Currently, no zdtm tests would generate UFFD_EVENT_{REMAP,REMOVE}.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The dup_page_read performs a shallow copy of a page_read object. It is
required for implementation of fork event in lazy-pages daemon.
When a restored process fork()'s a child, the lazy-pages daemon will handle
page faults of the child process, and it will use the parent process memory
dump for that.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Replace "pr<id>" with "pr<pid>-<id>" when printing information about a
particular page-read.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When the restored process calls mremap(), we will see #PF's on the new
addresses and we have to create a correspondence between the addresses
found in the dump and the actual addresses the process uses. For this
purpose we distinguish "live" address and "image" address in the lazy IOVs
and outstanding requests. The "live" address is used to find the
appropriate IOV and in uffd_copy and the "image" address is used to request
pages from the page-read.
If the mremap() call causes the mapping to grow, the additional part will
receive zero pages, as expected.
For the shrinking remaps, we will get UFFD_EVENT_UNMAP for the dropped part
of the mapping.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The UNMAP event is generated by userfaultfd when a VMA (or a part of it) is
unmapped from the process address space. We won't receive #PF's at the
unmapped range, but we need to make sure we are not trying to fill that
range at handle_remaining_pages.
Note, that the VMA is gone, so there is no sense to unregister uffd from
it.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When the restored process calls madvise(MADV_DONTNEED) or
madvise(MADV_REMOVE) the memory range specified by the madvise() call
should be remapped to zero pfn and we should stop monitoring this range in
order to avoid its pollution with data the process does not expect.
All we need to do here, is to unregister the memory range from userfaultfd
and the kernel will take care of the rest.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This is the version from linux-next at the moment.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
With address space manipulations, amount of pages that the lazy-pages
daemon will copy might differ from amount of pages we had in the dumps.
Disable the warning and error retval for now; we can restore the accounting
once uffd event handling stabilizes a bit.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The copied_pages and total_pages may be different because the process may
drop parts of its address space. And the IOVs list will be empty iff we are
done with the process.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently drop_lazy_iovs presumes that the range that should be dropped
starts inside an IOV. This works fine with page faults and background pages
but will fail for mapping changes.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The function essentially drops a memory range from lazy IOVecs
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When printing a message about particular process events, always prefix it
with "<pid>-<uffd>" for better log readability
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently we use pagemap to check if we should copy a page into process
address space or zero it. The lazy_iov'ecs can be used instead. If a
lazy_iov covers the faulting address, we should go ahead and read the page
and copy it. If there is not lazy_iov for the faulting address, just zero
it immediately.
Searching lazy_iov's rather than pagemap will also simplify upcoming
handling of UFFD_EVENT_REMAP.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Same meaning, less to type.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Multithreaded applications may concurrently generate page faults at the
same address, which will cause creation of multiple requests for remote
page, and, consequently, confuse the page server on the dump side.
We can keep track on page fault requests in flight and ensure this way that
we request a page from the remote side only once.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The kernel anyways does not really supports any flags for page fault
message and we've used '#if 0' to skip the flags processing. However, we
can just drop this chunk as we anyway will have do some more work than
simply removing '#if 0' to handle UFFD_WP.
travis-ci: success for lazy-pages: add non-#PF events handling (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It works faster and allows to check exit codes.
travis-ci: success for series starting with [1/2] page-server: don't return a server pid from page-server
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for crtools: close a signal descriptor after passing a preparation stage (rev6)
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The introduction of page-server send mode have broken the lazy dump because
instead of using existing pstree, the page server now tries to recreate the
pstree from the images.
Adding lazy_dump parameter to cr_page_server resolves this issue.
travis-ci: success for lazy-pages: fix lazy dump
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
To use lazy-pages from runc '--lazy-pages' functionality needs to be
accessible via RPC. This enables lazy-pages via RPC.
The information on which port to listen is taken from the
criu_page_server_info protobuf structure. If the user has enabled
lazy-pages via RPC only criu_page_server_info.port is evaluated
to get the listen port.
With additional patches in runc is it possible to use lazy-restore
with 'runc checkpoint' and 'runc restore'.
travis-ci: success for lazy-pages: enable lazy-pages via RPC
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Rename handle_user_fault to handle_uffd_event and split actual page fault
handling to a helper function
travis-ci: success for lazy-pages: add non-#PF events handling
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
If an event handler returns a positive value, the event polling and
handling loop is interrupted after all the pending events indicated by
epoll_wait are processed.
travis-ci: success for lazy-pages: add non-#PF events handling
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The number of pending events returned by epoll_wait is overridden by the
first call to an event handler. Using an additional local variable resolves
this issue.
travis-ci: success for lazy-pages: add non-#PF events handling
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently we are waiting for lazy-pages daemon to finish as a part of
.restore method, which may cause filling test process memory before the
test process resumed it's execution after call to test_waitsig(). In such
case, no page faults occur, but rather all the memory is copied in
handle_remaining_pages method in uffd.c.
Let's move wait(<lazy-pages-pid>,..) after call to test.stop().
travis-ci: success for lazy-pages: add non-#PF events handling
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for revert zero pagemaps
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for revert zero pagemaps
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Note, that since zero pages stats never been into master we can make
incompatible changes to stats image.
travis-ci: success for revert zero pagemaps
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The pagemap entries for pages mapped to zero pfn proved to be not useful...
travis-ci: success for revert zero pagemaps
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
A page that explicitly mapped to zero pfn or a page that is not present
should be treated in the same way, therefore the zero pagemaps are not
required and will be removed by the following commits.
travis-ci: success for revert zero pagemaps
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
If a page was not marked "present" at the dump time it will not be covered
by the pagemap and it will remain unmapped in the restored process. We
should uffdio_zero such pages and let kernel mm to take over.
travis-ci: success for revert zero pagemaps
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
CID 173076, issues/259
travis-ci: success for pagemap: verify the number of pages returned by receive_remote_pages_info
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This function does weird things, so better have it at least somehow
documented.
travis-ci: success for lazy-pages: add comments to update_lazy_iovecs
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Instead of checking for availability of userfaultfd late during the restore
process, make the detection of supported userfaultfd functionality part of
kerndat. As a bonus, I've extended criu check with ability to verify
presence of userfaultfd.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Use latest version from usefaultfd tree [1]. Judging by comments about the
last re-spin of userfaultfd updates, the API will go in "as is", so we can
pretty much rely on the current API definitions for proper detection of
supported userfaultfd features.
[1] https://git.kernel.org/cgit/linux/kernel/git/andrea/aa.git/
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Add pre-dump and remote-lazy-pages passes to criu-lazy-pages.sh
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently we poll userfaultfd for page faults and if there were no page
faults during 5 seconds we stop monitoring the userfaultfd and start
copying remaining pages chunk by chunk.
If a page fault occurs during the copy, the faulting process will be stuck
until the page it accessed would be copied to its address space.
This patch limits the initial "page fault only" stage to 1 second instead
of 5, and interleaves non-blocking poll of userfaultfd with copying of the
remaining memory afterwards.
travis-ci: success for lazy-pages: interleave #PF handling with transfers of remaining pages
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for lazy-pages: spelling: s/pagefalt/#PF
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
After commit a97d6d3f1609 (pagemap: replace seek_page with seek_pagemap
method), uffd only searches the pagemap containing the faulting page, but
it not for the page itself. For local restore it causes wrong data to be
read from pages*img and subsequent crash of the restored process.
Adding a call to pr->skip_pages fixes the problem.
travis-ci: success for lazy-pages: fix searching for the page at #PF time
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Lazy migration requires both dumped and restored processes to coexist at
the same time. This breaks some basic assumptions in the zdtm design.
Simulation of lazy migration with the page server allows testing most of
the involved code paths without major intervention into zdtm
infrastructure.
travis-ci: success for lazy-pages: improve testability (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The kernel support for lazy pages (userfaultfd) lacks many important
features which effectively prevents success in certain tests.
Allow skipping such test with somewhat informative message
travis-ci: success for lazy-pages: improve testability (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently, standalone page-server can only receive pages from the remote
dump. Extend it with the ability to serve local memory dump to a remote
lazy-pages daemon.
travis-ci: success for lazy-pages: improve testability (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Instead of crashing dump/page-server when a problem detected after the
page-pipe was split, print nice error messages and return error.
travis-ci: success for page-xfer: page_server_get_pages: replace BUG_ONs with 'return -1' (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Splitting of the trailing part of page-pipe buffer worked by coincidence
for single page requests. Request longer than a single page were not
handled correctly.
The proper point for splitting the trailing part of the page-pipe buffer is
the IOV following the IOV containing the desired page(s).
travis-ci: success for page-pipe: (yet another) fix for split page-pipe buffers (rev2)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for Some more cleanups over uffd.c (rev3)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
With epoll helpers in util we can stop exposing the
page-server socket to the oter world.
travis-ci: success for Some more cleanups over uffd.c (rev3)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
v2: Move epoll_prepare() too
travis-ci: success for Some more cleanups over uffd.c (rev3)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
The uffd code only needs the pstree items themselves, not
any IDs and relations they might have.
travis-ci: success for Some more cleanups over uffd.c (rev3)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This run away from previous set :) Two routines are now
identical, only page-read flags differ.
v2: Keep the uffd_hanle_pages() name
travis-ci: success for Some more cleanups over uffd.c (rev3)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Extend the RPC feature check functionality to also test for lazy-pages
support. This does not check for certain UFFD features (yet). Right now
it only checks if kerndat_uffd() returns non-zero.
The RPC response is now transmitted from the forked process instead of
encoding all the results into the return code. The parent RPC process
now only sends an RPC message in the case of a failure.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently, lazy dump starts page server regardless of errors that might
have been encountered at earlier stages. Fix it.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Le sigh.
travis-ci: success for more pr_perror() usage fixes
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Add a queue of async-read jobs into page-xfer. When the
page_server_sk gets a read event from epoll it reads as
many bytes into page_server_iov + page buffer as recv
allows and returns.
Once the full iov+data is ready the requestor is notified
and the next async read is started.
This patch removes calls to recv(...MSG_WAITALL) from all
remote async paths.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Finally, page_fault_local and page_fault_remote are
absolutely identical, so we can just merge them.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
This one is called by PR once IO is complete (right now
for sync cases only, more work is required here) and
lets us unify local and remote PF code in uffd.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
The _copy and _update_lazy_iovecs are both called by hands
once the data is ready.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
This flag means, that the PR_ASYNC is valid, but the IO
should be started ASAP. This is how remote reader works,
so this flag is mostly for the local reader. It will let
us unify page-fault handlers for local and remote cases.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
We already have routines that do send-req, recv-info
and recv-page, so no need in yet another one.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
All the "lower" page-read-s should have already arrived with
pre-dump. This fixes the combined scheme.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
The page transfer protocol is completely synchronous on the dump side,
therefore we can presume that when we get POLLIN event on the page server
socket it is either page info response for the last sent page request or
the page data following the last page info.
In the first case we set ev_data associated with page server socket events
to values received in receive_remote_page_info and in the second case we
reset ev_data to zero. This allows us to distinguish what was the reason
page_server_event have been called.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The synchronous remote page transfer prevents reception of uffd events
during the communications with the page server on the dump side. Adding
socket file descriptor to epoll_wait allows processing of incoming uffd
events after non-blocking request for remote page is issued and before the
dump side page server replies.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The asynchronous version of remote page_read will send the request to the
dump side and return happily.
The response will be handled by the uffd.c because it's epoll loop is the
only place where we can handle events.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This part of code is responsible for reseting pagemap to proper locatation,
and mapping requested address to zero pfn if needed. The upcoming addtions
to uffd.c will reuse this code.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
For asynchrounous page transfers in post-copy migration we need to be able
to request a remote pages, receive back information about the data is going
to arrive and receive the page data itself.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It will used by lazy-pages daemon to enable polling for reception of page
data from remote dump
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
In early days of uffd.c return value from uffd_copy was used to count
transferred pages. Since this is not the case anymore we can use 0 as
success.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently lazy-pages daemon uses either pr->read_pages or get_remote_pages
to get actual page data from local images or remote server. From now on,
page_read will be completely responsible for getting the page data.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently we allocate a single page to use as intermediate buffer for
holding data that will be used in UFFDIO_COPY. Let's allocate a buffer per
process and make that buffer large enough to hold the largest continuos
chunk.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
page_read->seek_page was restored to skip zero pagemaps, therefore we
should check its return value rather than underlying PME.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Inline relevant parts of get_page inside uffd_handle_page and call
uffd_{copy,zero}_page after we've got the data.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We will want to poll not only a bunch of uffd-s, but also the lazy
socket, so here's "an fd and a callback" object to be pushed into
epoll.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Instead of tracking memory handled by userfaultfd on the page basis we can
use IOVs for continious chunks.
travis-ci: success for uffd: A new set of improvements
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Right now the zdtm.py hacks around core code and waits for
a second for the socket to appear. Let's better make proper
--daemon mode for lazy-pages daemon and pidfile generation.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Instead of creating mm-related parts of restore info in process tree we
can directly use MmEntry for VMA traversals.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Moving the find_vmas and collect_uffd_pages functions before they are
actually used. This allows to drop forward declaration of find_vmas and
will make subsequent refactoring cleaner.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The event received should be checked to be #PF before
accessing its other arguments.
[ Mike:
Well, looking forward to see non-cooperative userfaultfd patches in kernel
we should have something like
static int handle_uffd_enent(struct lazy_pages_info *lpi)
{
read(&msg...);
switch (msg.event) {
case UFFD_EVENT_PAGEFAULT:
handle_pagefault(lpi, msg);
break;
default:
return -1;
}
}
But since this patch is anyway is a bugfix: <ack>
]
travis-ci: success for uffd: A set of improvements over criu/uffd.c
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
After previous patch we no longer need this hash since
we don't need fd -> lpi conversion.
travis-ci: success for uffd: A set of improvements over criu/uffd.c
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
This helps us get lpi MUCH faster on #PF.
travis-ci: success for uffd: A set of improvements over criu/uffd.c
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
This avoids excessive memcpy() one instruction below.
travis-ci: success for uffd: A set of improvements over criu/uffd.c
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
In cases errno is being set, we need to use pr_perror() to print it.
In cases errno is not set, we should use pr_err().
pr_perror() doesn't need a colon or a newline. pr_err() needs a newline.
Cc: Adrian Reber <areber@redhat.com>
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
travis-ci: success for Assorted nitpicks
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Use relative path for UNIX socket instead of absolute one.
This ensures we won't run into problems with invalid socket names.
travis-ci: success for lazy-pages: use relative path for UNIX socket
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Restore of a zombie process does not call setup_uffd which causes
lazy-pages daemon to stuck forever waiting for (pid, uffd) pair to arrive.
Let's extend the protocol between restore and lazy-pages so that for zombie
process a (0, -1) pair will be sent instead of actual (uffd, pid).
travis-ci: success for lazy-pages: misc fixes (rev4)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for lazy-pages: misc fixes (rev4)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
To properly handle zombie processes we will need to distinguish failures
coming from socket communications from absent userfault file descriptor
travis-ci: success for lazy-pages: misc fixes (rev4)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When a VMA is mapped with MAP_LOCKED it is address space is populated with
pages which causes UFFDIO_COPY to return -EXISTS. Until we can find some
better solution let's avoid marking VMAs with MAP_LOCKED as lazy.
Fixes: #238
travis-ci: success for lazy-pages: misc fixes (rev3)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Only the UFFD daemon is aware if pages are in the parent or not. The
restore will continue to work as any lazy-restore except that pages from
parent checkpoints will be pre-populated by the restorer.
The restorer will still register the whole memory region as being
handled by userfaultfd even if it contains pages from parent
checkpoints. Userfaultfd page faults will only happen on pages which
contain no data. This means from the parent pre-populated pages will not
trigger a userfaultfd message even if marked as being handled by
userfaultfd.
The UFFD daemon knows about pages which are available in the parent
checkpoints and will not push those pages unnecessarily to userfaultfd.
Following steps to migrate a process are now possible:
Source system:
* criu pre-dump -D /tmp/cp/1 -t <PID>
* rsync -a /tmp/cp <destination>:/tmp
* criu dump -D /tmp/cp/2 -t <PID> --port 27 --lazy-pages \
--prev-images-dir ../1/ --track-mem
Destination system:
* rsync -a <source>:/tmp/cp /tmp/
* criu lazy-pages --page-server --address <source> --port 27 \
-D /tmp/cp/2 &
* criu restore --lazy-pages -D /tmp/cp/2
This will now restore all pages from the parent checkpoint if they
are not marked as lazy in the second checkpoint.
v2:
- changed parent detection to use pagemap_in_parent()
v3:
- unfortunately this reverts
c11cf95afbe023a2816a3afaecb65cc4fee670d7
"criu: mem: skip lazy pages during restore based on pagemap info"
To be able to split the VMA-s in the right chunks for the restorer
it is necessary to make the decision lazy or not on the VmaEntry
level.
v4:
- everything has changed thanks to Mike Rapoport's suggestion
- the VMA-s are no longer touched or split
- instead of over 100 lines of changes this is now two line patch
Signed-off-by: Adrian Reber <areber@redhat.com>
Acked-by: Mike Rapoprot <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Combining pre-copy (pre-dump) and post-copy (lazy-pages) mode showed a
problem in the function page_pipe_split_ppb(). The function is used to
split the page-pipe-buffer so that it only contains the IOVs request
from the restore side during lazy restore.
Unfortunately it only splits the leading IOVs out of the
page-pipe-buffer and not the trailing:
Before split for requested address 0x7f27284d1000:
page-pipe: ppb->iov 0x7f0f74d93040
page-pipe: 0x7f27282bb000 1
page-pipe: 0x7f27284d1000 1
page-pipe: 0x7f27284dd000 2
After split:
page-pipe: ppb->iov 0x7f0f74d93050
page-pipe: 0x7f27284d1000 1
page-pipe: 0x7f27284dd000 2
and:
page-pipe: ppb->iov 0x7f0f74d93040
page-pipe: 0x7f27282bb000 1
This patch keeps on splitting the page-pipe-buffer until it contains
only the requested address with the requested length.
After split (still trying to load 0x7f27284d1000):
page-pipe: ppb->iov 0x7f0f74d93050
page-pipe: 0x7f27284d1000 1
and:
page-pipe: ppb->iov 0x7f0f74d93040
page-pipe: 0x7f27282bb000 1
and:
page-pipe: ppb->iov 0x7f0f74d93060
page-pipe: 0x7f27284dd000 2
v2:
- moved declarations to the declaration block
Signed-off-by: Adrian Reber <areber@redhat.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently potentially lazy pages are not counted as written even if they
are dump into pages*img. Count these pages as "pages_written" when dump is
not going to skip writing lazy pages to disk.
travis-ci: success for criu: mem: count all pages actually written to image as "pages_written"
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This translates pagemap flags into strings for easier readability.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Do the same here, the flags is now enough to tell hole
from pagemap.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
They are now the same and PE_PRESENT bit helps us distinguish
holes from pagemaps having pages inside.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
The ->write_hole and ->write_pagemap now look very much
alike, so let's merge them. This is preparatory patch
that makes holy type decision based on PE_FOO flags.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Instead of checking whether the VMA containing a page can be lazy for each
page, skip the entire parts of pagemap that have PE_LAZY flag set.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The PE_PRESENT flags is always set for pagemap entries that have
corresponding pages in the pages*img. Pagemap entries describing a hole
either with zero page or with pages in the parent snapshot will no have
PE_PRESENT flag set.
Pagemap entry that may be lazily restored is a special case. For the lazy
restore from disk case, both PE_LAZY and PE_PRESENT will be set in the
pagemap, but for the remote lazy pages case only PE_LAZY will be set.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
With 'zero' and 'lazy' booleans replaced by the flags field in
PagemapEntry, it is required that page-xfer will be aware of the change.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Having three booleans in pagemap entry clues for usage of good old flags.
Replace 'zero' and 'lazy' booleans with flags and use flags for internal
tracking of in_parent value. Eventually, in_parent may be deprecated.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Create the socket early so that it will be available after restoring the
namespaces
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Very minimalistic at the moment, no remote pages and namesapces.
Still better than nothing :)
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Cc: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We'll use it in anon shmem dedup so we need to have access
to it in shmem.c
Signed-off-by: Eugene Batalov <eabatalov89@gmail.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The UNIX sockets do not like relative paths. Assuming both lazy-pages
daemon and restore use the same opts.work_dir, their working directory full
path will be the same.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The remote lazy pages variant can be run as follows:
src# criu dump -t <pid> --lazy-pages --port 9876 -D /tmp/1 &
src# while ! sudo fuser 9876/tcp ; do sleep 1; done
src# scp -r /tmp/1/ dst:/tmp/
dst# criu lazy-pages --page-server --address dst --port 9876 -D /tmp/1 &
dst# criu restore --lazy-pages -D /tmp/1
In a nutshell, this implementation of remote lazy pages does the following:
- dump collects the process memory into the pipes, transfers non-lazy pages
to the images or to the page-server on the restore side. The lazy pages
are kept in pipes for later transfer
- when the dump creates the page_pipe_bufs, it marks the buffers containing
potentially lazy pages with PPB_LAZY
- at the dump_finish stage, the dump side starts TCP server that will
handle page requests from the restore side
- the checkpoint directory is transferred to the restore side
- on the restore side lazy-pages daemon is started, it creates UNIX socket
to receive uffd's from the restore and a TCP socket to forward page
requests to the dump side
- restore creates memory mappings and fills the VMAs that cannot be handled
by uffd with the contents of the pages*img.
- restore registers lazy VMAs with uffd and sends the userfault file
descriptors to the lazy-pages daemon
- when a #PF occurs, the lazy-pages daemon sends PS_IOV_GET command to the dump
side; the command contains PID, the faulting address and amount of pages
(always 1 at the moment)
- the dump side extracts the requested pages from the pipe and splices them
into the TCP socket.
- the lazy-pages daemon copies the received pages into the restored process
address space
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When appropriate, the lazy pages will no be written to the destination.
Instead, a pagemap entry for range of such pages will be marked with 'lazy'
flag.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The pages that are mapped to zero_page_pfn are not dumped but information
where are they located is required for lazy restore.
Note that get_pagemap users presumed that zero pages are not a part of the
pagemap and these pages were just silently skipped during memory restore.
At the moment I preserve this semantics and force get_pagemap to skip zero
pages.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Pagemap now is more friendly to random accesses, enable use of new APIs.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Fix CID 163485 (#2 of 2): Dereference null return value (NULL_RETURNS)
7. dereference: Dereferencing a pointer that might be null dest when
calling handle_user_fault.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This will allow to split a ppb so that data residing at specified address
will be immediately available
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
for buffers that contain potentially lazy pages
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
>>> >>> CID 161312: Error handling issues (NEGATIVE_RETURNS)
>>> >>> "task_args->uffd" is passed to a parameter that cannot be negative.
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
>>> >>> CID 161322: API usage errors (USE_AFTER_FREE)
>>> >>> Calling "close(int)" closes handle "client" which has already been closed.
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Now that userfaultfd/lazy-pages support is enable all the time, this
adds runtime detection of userfaultfd. On a system without the
userfaultfd syscall following is printed:
uffd daemon:
(00.000004) Error (uffd.c:176): lazy-pages: Runtime detection of userfaultfd failed on this system.
(00.000024) Error (uffd.c:177): lazy-pages: Processes cannot be lazy-restored on this system.
or criu restore
(00.457047) 6858: Error (uffd.c:176): lazy-pages: Runtime detection of userfaultfd failed on this system.
(00.457049) 6858: Error (uffd.c:177): lazy-pages: Processes cannot be lazy-restored on this system.
Signed-off-by: Adrian Reber <areber@redhat.com>
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Add linux/userfaultfd.h to criu sources. This header is a part
of the kernel API and I see nothing wrong to have in the repo.
Why we want to do this:
* to check that criu works correctly if a kernel doesn't
support userfaultfd.
* to check compilation of the userfaultfd part in travis-ci.
v2: remove UFFD from FEATURES_LIST
Acked-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Cc: Mike Rapoport <rppt@linux.vnet.ibm.com>
Cc: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
for holding state related to userfaultfd handling
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It verifies that amount of collected and transferred pages is consitent
and prints a summary
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It will handle page fault notifications from userfaultfd
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
so that listenning file descriptor might be used in select/poll
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
If CONFIG_HAS_UFFD is not defined an attempt to run the lazy pages daemon
will result in error message
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The __u64 is 'unsigned long' on Power and 'unsigned long long' on x86_64.
Using PRI?64 does not help because, for instance, PRIu64 is 'lu'.
According to [1] the solution is to define __SANE_USERSPACE_TYPES__ for
Power builds
[1] http://thread.gmane.org/gmane.linux.kernel/1425475/focus=1427433
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When get_page returns 0, it means that a page is mapped by a vma but it is
not found in the pagemap. This happens when a page is a zero page and
threofre skipped by dump.
Use UFFDIO_ZEROMAP to create a zero page in the restored process address
space.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
so that it'll be able to handle both UFFDIO_COPY and UFFDIO_ZEROPAGE
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The uffd_copied_pages can be incremented in uffd_copy_page function rather
than in its callers
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Most of the UFFD logic was in the function uffd_listen() which was
directly called from crtools.c. In preparation for the remote lazy
restore most of the code has been moved to separate function for better
integration of the network functionality.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
To better track how many pages have been handled by UFFD a few variables
have been made static global to easier access them and to reduce the
number of parameters passed around.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
uffd_listen() is a rather large function and this starts to move code
into subfunctions.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The variable vma_size was used for early debugging of lazy restore and
has no significance now.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Since VDSO pages cannot be lazy, no need to take care of them in lazy-pages
daemon.
Signed-off-by: Mike Rapoport <rapoport@il.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
VDSO is just a few pages and they can be loaded directly rather than go
through userfaultfd to save some complexity on the lazy-pages daemon side.
Signed-off-by: Mike Rapoport <rapoport@il.ibm.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
For a lazy restore via userfaultfd the lazy-pages daemon
needs to know which pages exist, so that it knows when all
pages have finally been migrated so that the restored process
has all of its memory. Therefore it needs to know which pages
exist and it needs to parse the files in the dump result directory.
The existing criu functions are designed to be used by a 'normal'
restore and thus a lot of assumptions are made what has to be set up.
For the lazy-pages restore the complete 'restore' initialization is
not necessary and therefore the criu common code dependencies are
minimized with this commit.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This is a first try to include userfaultfd with criu. Right now it
still requires a "normal" checkpoint. After checkpointing the
application it can be restored with the help of userfaultfd.
All restored pages with MAP_ANONYMOUS and MAP_PRIVATE set are marked as
being handled by userfaultfd.
As soon as the process is restored it blocks on the first memory access
and waits for pages being transferred by userfaultfd.
To handle the required pages a new criu command has been added. For a
userfaultfd supported restore the first step is to start the
'lazy-pages' server:
criu lazy-pages -v4 -D /tmp/3/ --address /tmp/userfault.socket
This waits on a unix domain socket (defined using the --address option)
to receive a userfaultfd file descriptor from a '--lazy-pages' enabled
'criu restore':
criu restore -D /tmp/3 -j -v4 --lazy-pages \
--address /tmp/userfault.socket
In the first step the VDSO pages are pushed from the lazy-pages server
into the restored process. After that the lazy-pages server waits on the
UFFD FD for a UFFD requested page. If there are no requests received
during a period of 5 seconds the lazy-pages server switches into a mode
where the remaining, non-transferred pages are copied into the
destination process. After all remaining pages have been copied the
lazy-pages server exits.
The first page that usually is requested is a VDSO page. The process
currently used for restoring has two VDSO pages, but only one is
requested
via userfaultfd. In the second part where the remaining pages are copied
into the process, the second VDSO page is also copied into the process
as it has not been requested previously. Unfortunately, even as this
page has not been requested before, it is not accepted by userfaultfd.
EINVAL is returned. The reason for EINVAL is not understood and
therefore
the VDSO pages are copied first into the process, then switching to
request
mode and copying the pages which are requested via userfaultfd. To
decide at which point the VDSO pages can be copied into the process, the
lazy-pages server is currently waiting for the first page requested via
userfaultfd. This is one of the VDSO pages. To not copy a page a second
time, which is unnecessary and not possible, there is now a check to see
if the page has been transferred previously.
The use case to use usefaultfd with a checkpointed process on a remote
machine will probably benefit from the current work related to
image-cache and image-proxy.
For the final implementation it would be nice to have a restore running
in uffd mode on one system which requests the memory pages over the
network from another system which is running 'criu checkpoint' also in
uffd mode. This way the pages need to be copied only 'once' from the
checkpoint process to the uffd restore process.
TODO:
* Contains still many debug outputs which need to be cleaned up.
* Maybe transfer the dump directory FD also via unix domain sockets
so that the 'uffd'/'lazy-pages' server can keep running without
the need to specify the dump directory with '-D'
* Keep the lazy-pages server running after all pages have been
transferred and start waiting for new connections to serve.
* Resurrect the non-cooperative patch set, as once the restored task
fork()'s or calls mremap() the whole thing becomes broken.
* Figure out if current VDSO handling is correct.
* Figure out when and how zero pages need to be inserted via uffd.
v2:
* provide option '--lazy-pages' to enable uffd style restore
* use send_fd()/recv_fd() provided by criu (instead of own
implementation)
* do not install the uffd as service_fd
* use named constants for MAP_ANONYMOUS
* do not restore memory pages and then later mark them as uffd
handled
* remove function find_pages() to search in pages-<id>.img;
now using criu functions to find the necessary pages;
for each new page search the pages-<id>.img file is opened
* only check the UFFDIO_API once
* trying to protect uffd code by CONFIG_UFFD;
use make UFFD=1 to compile criu with this patch
v3:
* renamed the server mode from 'uffd' -> 'lazy-pages'
* switched client and server roles transferring the UFFD FD
* the criu part running in lazy-pages server mode is now
waiting for connections
* the criu restore process connects to the lazy-pages server
to pass the UFFD FD
* before UFFD copying anything else the VDSO pages are copied
as it fails to copy unused VDSO pages once the process is running.
this was necessary to be able to copy all pages.
* if there are no more UFFD messages for 5 seconds the lazy-pages
server switches in copy mode to copy all remaining pages, which
have not been requested yet, into the restored process
* check the UFFDIO_API at the correct place
* close UFFD FD in the restorer to remove open UFFD FD in the
restored process
v4:
* removed unnecessary madvise() calls ; it seemed necessary when
first running tests with uffd; it actually is not necessary
* auto-detect if build-system provides linux/userfaultfd.h
header.
* simplify unix domain socket setup and communication.
* use --address to specify the location of the used
unix domain socket.
v5:
* split the userfaultfd patch in multiple smaller patches
* introduced vma_can_be_lazy() function to check if a page
can be handled by uffd
* moved uffd related code from cr-restore.c to uffd.c
* handle failure to register a memory page of the restored process
with userfaultfd
v6:
* get PID of to be restored process from the 'criu restore' process;
first the PID is transferred and then the UFFD
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This is a first try to include userfaultfd with criu. Right now it
still requires a "normal" checkpoint. After checkpointing the
application it can be restored with the help of userfaultfd.
All restored pages with MAP_ANONYMOUS and MAP_PRIVATE set are marked as
being handled by userfaultfd.
As soon as the process is restored it blocks on the first memory access
and waits for pages being transferred by userfaultfd.
To handle the required pages a new criu command has been added. For a
userfaultfd supported restore the first step is to start the
'lazy-pages' server:
criu lazy-pages -v4 -D /tmp/3/ --address /tmp/userfault.socket
This is part 1 of the userfaultfd integration which provides the
'lazy-pages' server implementation.
v2:
* provide option '--lazy-pages' to enable uffd style restore
* use send_fd()/recv_fd() provided by criu (instead of own
implementation)
* do not install the uffd as service_fd
* use named constants for MAP_ANONYMOUS
* do not restore memory pages and then later mark them as uffd
handled
* remove function find_pages() to search in pages-<id>.img;
now using criu functions to find the necessary pages;
for each new page search the pages-<id>.img file is opened
* only check the UFFDIO_API once
* trying to protect uffd code by CONFIG_UFFD;
use make UFFD=1 to compile criu with this patch
v3:
* renamed the server mode from 'uffd' -> 'lazy-pages'
* switched client and server roles transferring the UFFD FD
* the criu part running in lazy-pages server mode is now
waiting for connections
* the criu restore process connects to the lazy-pages server
to pass the UFFD FD
* before UFFD copying anything else the VDSO pages are copied
as it fails to copy unused VDSO pages once the process is running.
this was necessary to be able to copy all pages.
* if there are no more UFFD messages for 5 seconds the lazy-pages
server switches in copy mode to copy all remaining pages, which
have not been requested yet, into the restored process
* check the UFFDIO_API at the correct place
* close UFFD FD in the restorer to remove open UFFD FD in the
restored process
v4:
* removed unnecessary madvise() calls ; it seemed necessary when
first running tests with uffd; it actually is not necessary
* auto-detect if build-system provides linux/userfaultfd.h
header
* simplify unix domain socket setup and communication.
* use --address to specify the location of the used
unix domain socket
v5:
* split the userfaultfd patch in multiple smaller patches
* introduced vma_can_be_lazy() function to check if a page
can be handled by uffd
* moved uffd related code from cr-restore.c to uffd.c
* handle failure to register a memory page of the restored process
with userfaultfd
v6:
* get PID of to be restored process from the 'criu restore' process;
first the PID is transferred and then the UFFD
* code has been re-ordered to be better prepared for lazy-restore
from remote host
* compile test for UFFD availability only once
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
For the upcoming userfaultfd integration the lazy-pages mode needs to
setup the criu infrastructure to read the pages files.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The ppc64le docker image has broken /etc/apt/sources.list. A small fixup to
it allows running ppc64le tests.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The biggest new thing this time is s390x arch support!
Also we have several improvements and a set of bugfixes
as usual.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Since commit ced9c529f6 ("restore: fix race with helpers' kids dying
too early"), we block SIGCHLD in helper tasks before CR_STATE_RESTORE.
This way we avoided default criu sighandler as it doesn't expect that
childs may die.
This is very racy as we wait on futex for another stage to be started,
but the next stage may start only when all the tasks complete previous
stage. If some children of helper dies, the helper may already have
blocked SIGCHLD and have started sleeping on the futex. Then the next
stage never comes and no one reads a pending SIGCHLD for helper.
A customer met this situation on the node, where the following
(non-related) problem has occured:
Unable to send a fin packet: libnet_write_raw_ipv6(): -1 bytes written (Network is unreachable)
Then child criu of the helper has exited with error-code and the
lockup has happened.
While we could fix it by aborting futex in the end of
restore_task_with_children() for each (non-root also) tasks,
that would be not completely correct:
1. All futex-waiting tasks will wake up after that and they
may not expect that some tasks are on the previous stage,
so they will spam into logs with unrelated errors and may
also die painfully.
2. Child may die and miss aborting of the futex due to:
o segfault
o OOM killer
o User-sended SIGKILL
o Other error-path we forgot to cover with abort futex
To fix this deadlock in TASK_HELPER, as suggested-by Kirill,
let's check if there are children deaths expected - if there
isn't any, don't block SIGCHLD, otherwise wait() and check if
death was on expected stage of restore (not CR_STATE_RESTORE).
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Conflicts:
criu/cr-restore.c
This is an extract from Kirill Tkhai's patch
87464739 (restore: Block SIGCHLD during root_item initialization)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
E.g, if child was killed by SIGSEGV, this message
previously was "exited, status=11", as si_code == CLD_DUMPED == 3
in this case will result in (si_code & CLD_KILLED) == (si_code & 1).
Which is misleading as you may try to look for exit() calls
with 11 arg.
Correct if to compare si_code with CLD_*.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
venet is not virtuozzo specific but rather
came from openvz, make it so.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is good to know what command were executed.
https://github.com/xemul/criu/issues/371
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
It turned out (surprise surprise) that page server exchanges CR_FD_PAGEMAP
and CR_FD_SHMEM_PAGEMAP values in ps_iov_msg. The problem is that these
constants sit in enum and change their values from version to version %)
So here's the fixed version of the protocol including the backward compat
checks on all the values that could be met from older CRIUs (we're lucky
and they didn't intersect).
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There's two issues with this code:
1. Child task is killed by parent faster, than it could print the line.
2. Even if it had time to print it - there would always be 0, because
it's called from child process.
Obviously, this print was meant to be in parent process. So, let's move
it there.
Signed-off-by: Vitaly Ostrosablin <vostrosablin@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As of manual page INSTALL.md, it is stated that those variables can be
overridden by means of environmental variables.
export BINDIR="somedir"
export SBINDIR="somedir"
export LIBDIR="somedir"
export MANDIR="somedir"
export INCLUDEDIR="somedir"
export LIBEXECDIR="somedir"
make install
But those settings will not be honored, sticking to default Makefile values.
This patch fixes the issue.
Signed-off-by: Francesco Giancane <francescogiancane8@gmail.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I tried to build and install the criu package from source. All went
well, unless for the install part.
In particular,
PREFIX=/
DESTDIR=~/build_criu
PREFIX=${PREFIX} DESTDIR=${DESTDIR} make install
resulted in installing criu packages in ~/build_criu/usr/local/,
ignoring PREFIX, even if this variable should be configurable as of
manual and GCS.
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Francesco Giancane <francescogiancane8@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When files are added to the report shutil.copytree is unhappy with
lazy-pages.socket. Tell shutil.copytree that it should ignore *.socket.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise someone can include kerndat.h before config.h
and get another kerndat structure. For example, proc_parse
doesn't include config.h and Cyrill met this problem.
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There's potential NULL-derefernece in dump_netns_con() -- two xmalloc
results are not checked. However, since there's a huge set of these
xmallocs, I propose to relax the whole thing with one big xmalloc and
xptr_pull() helper.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's unused and it's rewritten in shmem_wait_and_open(),
and it just confuses a reader. So, kill it.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
For dumping threads we execute parasite code before we collect the
floating point registers with get_task_regs().
The following describes the code path were this is done:
dump_task_threads()
for (i = 0; i < item->nr_threads; i++)
dump_task_thread()
parasite_dump_thread_seized()
compel_prepare_thread()
prepare_thread()
### Get general purpose registers ###
ptrace_get_regs(ctx->regs)
### parasite code is executed in thread ###
compel_run_in_thread(tctl, PARASITE_CMD_DUMP_THREAD)
compel_get_thread_regs()
### Get FP and VX registers ###
get_task_regs()
Since on s390 gcc uses floating point registers to cache general
purpose without the -msoft-float option the floating point
registers would have been clobbered after compel_run_in_thread().
With this patch we first save all thread registers with task_get_regs() and
then call the parasite code.
We introduce a new function arch_set_thread_regs() that restores the saved
registers for all threads. This is necessary for criu dump --leave-running,
--check-only, and error handling.
Pre-dump does not require to save the registers for the threads because
because only the main thread (task) is used for parsite code execution.
The above changes allow us to use all register sets in the parasite
code - therefore we can remove -msoft-float on s390.
Reviewed-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This test can be used to verify FP and VX registers on s390:
- Verify that "criu restore" sets the correct register sets
from "criu dump":
$ zdtmp.py run -t zdtm/static/s390x_regs_check
- Verify that dumpee continues running with correct registers after
parasite injection:
$ zdtm.py run --norst -t zdtm/static/s390x_regs_check
$ zdtm.py run --norst --pre 2 -t zdtm/static/s390x_regs_check
$ zdtm.py run --check-only -t zdtm/static/s390x_regs_check
Reviewed-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We have to include Makefile.inc earlier in order to use SRCARCH.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This fixes the ppc64el build failure
CC criu/arch/ppc64/sigframe.o
In file included from criu/arch/ppc64/sigframe.c:5:0:
criu/arch/ppc64/include/asm/types.h:32:0: error: "AT_VECTOR_SIZE_ARCH" redefined [-Werror]
#define AT_VECTOR_SIZE_ARCH 6
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The entries in /proc/<pid>/maps look like the following:
3fffffdf000-40000000000 rw-p 00000000 00:00 0
The upper address is the first address that is *not* included in the
address range.
Our function max_mapped_addr() should return the last valid address
for a process, but currently returns the first invalid address.
This can lead to the following error message on kernel that have
kernel commit ee71d16d22bb:
Error (criu/proc_parse.c:694): Can't dump high memory region
1ffffffffff000-20000000000000 of task 24 because kernel commit ee71d16d22bb
is missing
Fix this and make max_mapped_addr() the last valid address (first invalid
address - 1).
Reported-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We currently define "CFLAGS += -msoft-float -fno-optimize-sibling-calls"
in Makefile.compel.
Makefile.compel is included into the toplevel Makefile and so changes
CFLAGS which are exported to all criu and zdtm Makefiles.
We must not use -msoft-float outside the compel files. E.g. otherwise for
zdtm we get the following build error:
uptime_grow.o: In function `main':
/tmp/2/criu/test/zdtm/static/uptime_grow.c:36: undefined reference to `__floatdidf'
/tmp/2/criu/test/zdtm/static/uptime_grow.c:36: undefined reference to `__muldf3'
/tmp/2/criu/test/zdtm/static/uptime_grow.c:36: undefined reference to `__floatdidf'
/tmp/2/criu/test/zdtm/static/uptime_grow.c:36: undefined reference to `__adddf3
Fix this and move the CFLAGS definition to the compel Makefiles.
We do this by defining a new flag CFLAGS_PIE that is only used for pie code.
Reported-by: Adrian Reber <areber@redhat.com>
Suggested-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Tested-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We have to use "debian.jessie" instead of "ubuntu.xenial" because
qemu-s390x-static can only run z900 instructions and Ubuntu is
built with a more recent architecture level set.
We first enable only gcc because there are still some issues with clang.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Debian is compiled for z900 - therefore we can't use the "laa"
instruction.
Fix this and replace "laa" by the older "cs" (compare and swap) loop.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The flogr instruction not supported by debian jessie (z900).
So replace it by the gcc built-in.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Use the "-fno-optimize-sibling-calls" gcc option to prevent GOT relocations
caused by gcc versions without the commit "S/390: Fix 64 bit sibcall":
* https://gcc.gnu.org/viewcvs/gcc?view=revision&revision=233169
Otherwise we get compile errors like:
GEN criu/pie/parasite-blob.h
Error (compel/src/lib/handle-elf-host.c:572):
Unsupported relocation of type 26
Those can be caused by the following relocation types:
* R_390_GOTENT (e.g. RHEL7 based systems)
* R_390_GOTPCDBL (e.g. Debian Jessie)
* R_390_GOT12 (e.g. Debian Jessie)
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For kernels that don't have commit ee71d16d22 ("s390/mm: make TASK_SIZE
independent from the number of page table levels") criu sets TASK_SIZE
to 4 TB on s390 (see compel_task_size()).
When dumping tasks >= 4 TB on such systems, we would silently loose
memory >= 4TB.
So add a check and refuse to dump the task in that case.
When restoring tasks >= 4 TB on such systems, the remap() call for
moving the vmas at the end of the restor process would fail
and a very unclear error message is printed.
So add a check and write a more speaking error message in that case.
Reviewed-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On s390 we have special console drivers with minors 64 and 65.
Add support for them in criu code and in zdtm testsuite.
Reviewed-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If the kernel contains patch ee71d16d22 ("s390/mm: make TASK_SIZE
independent from the number of page table levels") we are able
to checkpoint tasks > 4TB.
Add a testcase to verify this.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add s390 parts to common code files.
Patch history
-------------
v2->v3:
* Add: Fix big endian byte order checks
Reviewed-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add s390 parts to common code files.
Patch history
-------------
v2->v3:
* Add: s390: Consolidate -msoft-float into Makefile.compel
Reviewed-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch only adds the support but does not enable it for building.
Reviewed-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Same here -- now when we collect info and driver at the same
place late enough we can verify info once, then attach to
files.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since we need tty driver for info, we may lookup the guy
when collecting info, not when attaching it to a file.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are two object for TTY files -- the file itself and tty_info.
The latter is effectively an inode image. Right now we collect infos
before files, so that latter can find former and attach to it.
In order to move tty files on generic file entry we need to collect
files very early, much earlier, that infos. So here's the patch that
changes the order of tty file vs info collection.
The general idea is -- when collecting files put them in a list and
when an info arrives it walks that list and attaches ttys to self.
Next patches will also add some optimization available with that
scheme.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are two goals of this merge. First is to reduce the amount
of image files we generate and scan on restore. The latter is
more importaint, as even if we have no weird stuff like signalfd,
we still try to open this file. So after the merge we try to
open ~15 image files (out of ~30) less %) which is nice.
The 2nd goal is to simplify the C/R support for SCM messages.
This becomes possible with the fact, that all files we have can
be distinguished by their ID only, w/o type. This, in turn,
makes image layout for SCMs much simpler.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I'm about to merge all the file images into one big image,
so here's the place that would read it and collect.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
(Try to) Fix the readme problems found by the feedmereadmes guys:
* Tuned up the tagline
* Added info about what for, history, competitors, etc.
* Put more links for potential contributors
This device is an API endpoint, just skip it. Also, prepare the
ground for sit dump.
Issue #11
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Most of the changes this time are preparation for future
new features and optimizations, that hasn't yet been well
tested and polished.
However, we have several new features. The most important
one is the --tcp-close option to help migration of Docker
containers, that constantly change their IP address.
And, as usually, a set of bugfixes.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The struct fd_link link allocated in inner context might be
freed before dump call (depending on compiler), instead
use a safer approach.
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The unified hierarchy controller doesn't have any name, so criu hangs
while parsing this sort of strings.
Let's skip those for now, until we implement cgroup2 support.
https://github.com/xemul/criu/issues/252
v2: Code comments
Reported-and-tested-by: Adrian Reber <adrian@lisas.de>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It looks like this call to open_image was left from the
times when we reworked packets sending and collected
them early.
✓ travis-ci: success for sk-packet: Don't open image when not needed
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Code for tcp-close option was added after boolean-valued options
were modified to accept their negations as well. Since tcp-close
option works only with boolean values and does not accept any
argument, it should be wriiten in the same manner to allow users
to override the value when using configuration files.
Signed-off-by: Veronika Kabatova <vkabatov@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Only long options are supported in configuration files. "-v" is the only
short option which doesn't have a corresponding long option, therefore
users wouldn't be able to setup verbosity in configuration files without
this patch.
Signed-off-by: Veronika Kabatova <vkabatov@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Use "union semun" for semctl() to make testcase also work on s390x.
Signed-off-by: Alice Frosi <alice@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The TEST_STRING "Hello World!" has 13 bytes size. Therefore the 10 bytes
used for the buffer size are not sufficient.
Fix this and use sizeof() to be on the safe side.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The "args" parameter in apply_sb_flags() is unsigned long. Therefore also
use unsigned long for the cast.
The "sflags" variable in do_new_mount() is unsigned long. Therefore use
sizeof(sflags) instead of sizeof(int).
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The htole64() function returns a 64 bit value. This is stored in
a 32 bit integer in wait_fds_event() which results in 0 for big-endian
64 bit platforms. The fuxtex() system call also requires 32 bit values.
Fix this and use htole32() also for 64 bit platforms.
Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Newer glibc releases have removed SIGUNUSED from bits/signum.h which
breaks building criu on those systems:
https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff;h=8082d91e1c449e0cb137468b731004a5e605c8c6
SIGSYS returns the same value as SIGUNUSED and testing has shown
that criu still successfully completes zdtm with this patch.
Signed-off-by: Adrian Reber <areber@redhat.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The remap is searhced by dev:ino pair that is known only when
root task starts (and opend the remap). The collection stage
is about to happen in crtools, so move the resolve in post-prep.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The call to unlink() should happen in root task context,
while the collection stage is about to be moved into the
crtools, so keep the stale-unlink piece in post-prep
for a socket.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the continuation of the previous patch.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Having pprep_head built-in it becomes much easier
to do socket-by-socket peer resolution.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Having ppreh_heads we can simplify the _once helper
by re-using the .next field.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now the post-prep actions are xmalloc()-ed then added to the list.
Let's make it sit right on the structures that need the post-prep,
this would make some things much simpler and nicer soon.
The approach is inspired by kernel rcu_head-s :)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This flag now means "image was opened", while the "empty image"
concept makes this always true. Since there's one user of this
flag, which is obviously incorrect, remove the latter and fix
the former to mean "at least one object was read".
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't want to run tests, if a kernel has a problem. And we want
to know when the taint flag is changed.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With the recent cleanups in fdinfo parsing the memory
allocation policy for entries has changed, thus keeping
a pointer on the entry handle is no longer valid (it
will be freed soon).
Said that -- duplicate the memory for queued irmap work.
https://github.com/xemul/criu/issues/328
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
'tcp-close' is a option that replaces connected tcp-sockets with
'closed' ones during restoring, therefore it have no sense without
restore stage. Thus let's skip related tests if the 'norst' flag was
specified.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1: Signed underflow
criu/files-reg.c: In function ‘open_path’:
criu/files-reg.c:1299:14: error: iteration 2147483647
invokes undefined behavior [-Werror=aggressive-loop-optimizations]
while (count--) {
~~~~~^~
2: Uninitialized variable
criu/files-reg.c: In function ‘make_parent_dirs_if_need’:
criu/files-reg.c:1354:13: warning: ‘count’ may be used uninitialized in
this function [-Wmaybe-uninitialized]
P.S. arch linux 4.7.5-1. gcc (GCC) 6.3.1 20170109
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case of success, we want to be silent when on default log level.
This is a time-honored UNIX tradition, who we are to break it?
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Surprisingly, but
offsetof(inotify_wd_entry, node) == offsetof(fanotify_mark_entry, node)
even though both structures have node field in the middle and the
fields sitting above one are totally different.
So the code works, but ... we're risking :)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If the ghost file is too big, it might make sence to try seeking
for holes in it, thus reducing the image size.
We've seen this once for tmpfs files in issue #230.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't need gf there, but will need more than just mode.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
GCC isn't happy if we use %rbp as register for local variable
with -ggdb3 option.
Which resulted in the following build error for `make DEBUG=1`:
> In file included from criu/arch/x86/crtools.c:10:0:
> criu/arch/x86/include/asm/compat.h: In function ‘do_full_int80’:
> criu/arch/x86/include/asm/compat.h:50:1: error: bp cannot be used in asm here
Fix it by saving/restoring %rbp around 32-bit syscall manually.
Just while at it - add a comment about r8-r11 clobbers.
Reported-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are 2 test cases:
1. Connected socket should be restored in the closed state
2. Listening socket state should not change after restore
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Eugene Batalov <eabatalov89@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
New restore option 'tcp-close' was introduced. It restores all connected
TCP sockets in TCP_CLOSE state. Here we consider tcp sockets in
TCP_ESTABLISHED, TCP_FIN_WAIT2, TCP_FIN_WAIT1, TCP_CLOSE_WAIT,
TCP_LAST_ACK, TCP_CLOSING, TCP_SYN_SENT states as connected sockets.
This is consistent with current CRIU usage of these states. Thus this
option doesn't affect sockets with original states of TCP_LISTEN and
TCP_CLOSE.
Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: Eugene Batalov <eabatalov89@gmail.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Pack repeated actions in one. Also, fixed the "return -1"
from the middle of restore_task_with_children(),
while cleanup is need.
v2: goto err in case of error instead of return -1.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is a hot-fix with a regression fix and an urgent
support for the latest-n-greatest kernel API change.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Currently this is lsm.c's static variable, but since kdat
is now cached (and uncached) this value stays zero (no lsm)
if the cache file gets loaded, which is obviously wrong and
breaks the restore all the time on lsm-enabled hosts.
https://github.com/xemul/criu/issues/323
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is to remove the function pointer and have only "type"
variable left.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to keep the host LSM mode on kerndat (next patches),
at the same time the --lsm-profile option needs to correspond
to it.
So split the option handling into two parts -- first keep it
as is, next -- check for kerndat correspondance.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
"With the recent kernel changes criu should never look outside of start-end
region reported by /proc/maps; and restore doesn't even need to know if a
GROWSDOWN region will actually grow or not, because (iiuc) you do not need
to auto-grow the stack vma during restore, criu re-creates the whole vma
with the same length using MAP_FIXED and it should never write below the
addr returned by mmap(MAP_FIXED)" // Oleg
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If the guard page is not reported in show_map_vma we should
not ajust vma address neither we should call unmap_guard_pages
in restorer.
https://github.com/xemul/criu/issues/322
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In vanilla kernel commit 1be7107fbe18eed3e319a6c3e83c78254b693acb
show_map_vma() no longer report PAGE_SIZE. Detect it with
simple test and remember in kdat settings.
Suggested-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the no-new-features release :) We have several bugfixes,
memory restore optimization and a little bit more.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The list in question is not used for fles nowadays.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This case is legacy, tfds are merged into epoll entry, but
to make it working we have separate list of tfds and extra
code in ->open callback.
Keep the legacy code in one place.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Current collect helper frees the pb entry if there's
zero priv_size on cinfo. For files we'll have zero
priv_size (as entries will be collected by sub-cinfos),
while the entry in question should NOT be freed.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Rather than do open/close to reset pagemap, just update it's state.
Signed-off-by: Mike Rapoport <rppt@linux.vnet.ibm.com>
Acked-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
For the upcoming userfaultfd integration the skip_pages functionality is
required to find the userfaultfd requested pages.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Previous patch (5a1e1aac) tried to minimize the amount of
open()s called when mmap()ing the files. Unfortunatley, there
was a mistake and wrong flags were compared which resulted in
the whole optimization working randomly (typically not
working).
Fixing the flags comparison revealed another problem. The
patch in question correllated with the 03e8c417 one, which
caused some vmas to be opened and mmaped much later than the
premap. When hitting the situation when vmas sharing their
fds are partially premapped and partially not, the whole
vm_open sharing became broken in multiple places -- either
needed fd was not opened, or the not needed left un-closed.
To fix this the context, that tracks whether the fd should
be shared or not, should be moved from collect stage to
the real opening loop. In this case we need to explicitly
know which vmas _may_ share fds (file private and shared)
with each other, so the sharing knowledge becomes spread
between open_filemap() and its callers. Oh, well...
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On real apps it's typical to have sequences ov VMAs with
absolutely the same file mapped. We've seen this dump-time
and fixed multiple openings of map_files links with the
file_borrowed flag.
Restore situation is the same -- the vm_open() call in many
cases re-open the same path with the same flags. This slows
things down.
To fix this -- chain VMAs with mapped files to each other
and only the first one opens the file and only the last
one closes it.
✓ travis-ci: success for mem: Do not re-open files for mappings when not required
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
In this routine we'll need to compare fdflags, so to
avoid double if-s, let's calculate and set fdflags early.
✓ travis-ci: success for mem: Do not re-open files for mappings when not required
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
When a vma we restore doesn't have any pages in pagemaps there's
not need to enforce PROT_WRITE bit on it.
This only applies to non-premmaped vmas.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Performance experiments show, that we spend (relatively) a lot of time
mremap-ing areas from premap area into their proper places. This time
depends on the task being restored, but for those with many vmas this
can be up to 20%.
The thing is that premapping is only needed to restore cow pages since
we don't have any API in the kernel to share a page between two or more
anonymous vmas. For non-cowing areas we map mmap() them directly in
place. But for such cases we'll also need to restore the page's contents
also from the pie code.
Doing the whole page-read code from PIE is way too complex (for now), so
the proposal is to optimize the case when we have a single local pagemap
layer. This is what pr.pieok boolean stands for.
v2:
* Fixed ARM compiling (vma addresses formatting)
* Unused tail of premapped area was left in task after restore
* Preadv-ing pages in restorer context worked on corrupted iovs
due to mistakes in pointer arithmetics
* AIO mapping skipped at premap wasn't mapped in pie
* Growsdown VMAs should sometimes (when they are "guarded" by
previous VMA and guard page's contents cannot be restored in
place) be premmaped
* Always premmap for lazy-pages restore
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Next patch will stop premapping some private vmas. In particular -- those,
that are not COW-ed with anyone. To make this work we need to distinguish
vmas that are not cowed with anyone from those cowed with children only.
Currently both have vma->parent pointer set to NULL, so for former let's
introduce the special mark.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Inherited VMAs don't need the descriptor to work with.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Collect VMAs into COW-groups. This is done by checking each pstree_item's
VMA list in parallel with the parent one and finding VMAs that have
chances to get COW pages. The vma->parent pointer is used to tie such
areas together.
v2:
* Reworded comment about pvmas
* Check for both vmas to be private, not only child
* Handle helper tasks
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We currently keep pointer on parent vma bitmap, but more info
about the parent will be needed soon.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Not all private VMA-s will be premmaped, so a separate sign of
a VMA being on the premap area is needed.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The page-read will be needed during the premap stage.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I've met missing vvar on Virtuozzo 7 kernel - just skip
unmapping it.
TODO: check ia32 C/R with kernel CONFIG_VDSO=n
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I've deleted it previously by the reason that I searched
vdso vma in [vdso/vvar] vma's pair by magic header.
So, I needed to suppress this error.
>From that moment, I've reworked how 32-bit vdso is parsed
and now we don't need to search it, even more: we parse it
only once in the criu helper.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On x86_64 defconfig it's =m, so if you boot kernel without initramfs
in qemu, you will see this.
[xemul: split long line]
Fixes: #292
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I was adapting CRIU with ia32 support for building with Koji,
and found that Koji can't build x86_64 packages and have
i686 libs installed.
While at it, I found that i686 libraries requirement is
no longer valid since I've deleted the second parasite.
Drop feature test for i686 libs and put test for gcc.
That will effectively test if gcc can compile 32-bit code
and bug with debian's gcc (#315).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I need to add feature test written in assembly to check
if the feature can be compiled.
Add a make function for this purpose.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After commit 2e8970beda "mount: create a mount point
for the root mount namespace in the roots yard", top
of the tree of mount_infos points to the fake mount.
So, when we're looking for appropriate place for
binfmt_misc, we can't find "xxx/proc/sys/fs/binfmt_misc".
Fix that by finding real NS_ROOT manually.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The routine in question just sets up the mutex to access
/dev/ptmx. This initialization can be done when we collect
a single tty.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
No need to schedule both post-actions, we can merge them. This
also sanitizes the "void *unised" arguments for both.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This routine just initializes the remap open lock,
and there's already the code that initializes the
whole remap engine.
Re-arrange this part.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Now this lock is only needed to serialize remap open
code, so name it such.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Ghost remaps allocate path with shmalloc. Add comment
why this is such.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We used to have users counter on remap which was
incremented each time this routine was called. Nowadays
remaps are managed w/o the refcounting and we no
longer need global mutex protection for it.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
There's no need in separate call to prepare_procfs_remaps().
All remaps are collected one step earlier and we can do
open_remap_dead_process() right at once.
Also rename the latter routine.
✓ travis-ci: success for Sanitize initialization bits
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This just moves all the deprecated code into one place.
✓ travis-ci: success for Sanitize fsnotify legacy code
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
The lists are only needed to collect marks (deprecated) into
notify objects. The latter ones are stored in fdsec hash, so
for this legacy case we can find them there.
✓ travis-ci: success for Sanitize fsnotify legacy code
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Marks images were merged into regular in 1.3.
✓ travis-ci: success for Sanitize fsnotify legacy code
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We only needed it for kernel 3.19. Apparently, Ubuntu 14.04.5 comes
with a kernel from 16.04 (i.e. 4.4), so we can disable this workaround!
Anyway, just in case, let's do it conditionally.
While at it, slightly improve the comment.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
asciidoc pulls in a lot of dependencies, most of those are not
needed as we just use it to convert txt to a man page. Adding
--no-install-recommended option to apt-get makes it skip those
additional dependencies. The only needed package is xmlto, so
let's add it explicitly.
This results is some 50 packages being skipped (mostly TeX/LaTeX and
some extra SGML tools), wow!
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we support restoring opened /dev/tty reference
if only control terminal belongs to the same process,
ie no inheritance is allowed.
Thus we should refuse to dump in such scenario
otherwise restore will fail.
Reported-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently it is only used to get a file descriptor to the mount
namespace root, but if we have only one mntns, we can open "/".
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Processes can be restored in another mntns, so mnt_id will be
useless in this case. If mntns isn't dumped, we have to dump a path
to a mount point.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There were kernel bug with 32-bit mmap() returning 64-bit pointer.
The fix is in Torvalds master, will be released in v4.12 kernel.
Checkpointing after v4.9 kernel works good, but restoring will
result in application which will mmap() 64-bit addresses resulting
in segfault/memory corruptions/etc.
As our policy is fail on dump if we can't restore on the same target,
error checkpointing for v4.9.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The idea is simple. Everyone has to wait its children,
a restore is interrupted if we found abandoned zombie.
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We currently can batch pagemap entries into page-read list, but will
need to queue them into per-pstree_entry one.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The pages.img will need to get opened one more time w/o the pagemap.img.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1. Commit 8b99809 ("compel: make plugins .a archives") changed the
suffix of compel plugins, so this test no longer compiles.
2. "compel plugins" can print auxiliary plugins now, let's use it.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As we have more than 1 working plugin right now, let's implement
the TODO item for "compel plugins" command.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Ubuntu 14.04 (Travis) doesn't have it.
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Looks-good-to: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Apparently, setup.py from distutils interprets --root= option without
an argument as "--root=." and we end up with what is described
in https://github.com/xemul/criu/issues/309.
Fix is to prepend DESTDIR value (if any) to --prefix argument.
v2: fix uninstall as well
v3: same code, resent via gmail
Reported-by: Juraj Oršulić <juraj.orsulic@fer.hr>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
soccr.h:
After previous patch <linux/types.h> is not needed anymore,
<netinet/tcp.h> is needed as we test for it in feature tests,
i.e., struct tcp_repair_window is declared there.
Also drop forward-declaration of (struct libsoccr_sk) - it's
declared again below.
soccr.c:
Sort headers by name so errors like twice-including errno.h
will not happen again. Also remove assert.h.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As uint32_t already has occupied the header, use it for all 32-bit
unsigns. That will allow to drop additional include <linux/types.h>.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The same as for Checkpointing - we need to call 32-bit syscall
for compatible tasks here to correctly restore compat_robust_list,
not robust_list.
Note: I check here restorer's *task* arg for compatible mode, not
restorer *thread* arg. As changing application's mode during runtime
is very rare thing itself, application that runs different bitness
threads is most likely not present at all.
If we ever meet such application, this could be improved.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The kernel keeps two different pointers for 32-bit and 64-bit futex
lists: robust_list and compat_robust_list in task_struct.
So, dump compat_robust_list for ia32 tasks.
Note: this means that one can set *both* compat_robust_list and
robust_list pointers by using as we're here 32-bit and 64-bit syscalls.
That's one of mixed-bitness application questions.
For simplification (and omitting more syscalls), we dump here only
one of the pointers.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Check for presence of robust futex list is in the reality
(futex_rla_len != 0).
That does code on dumping, in get_task_futex_robust_list():
> ret = syscall(SYS_get_robust_list, pid, &head, &len);
> if (ret < 0 && errno == ENOSYS) {
[..]
> len = 0;
[..]
> }
[..]
> info->futex_rla_len = (u32)len;
And in images: futex_rla_len == 0 means that futex is not present.
So, we don't need additional restorer's parameter `has_futex'
which is always true, remove it.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Modules pre-load is also slow, but guarding this code with
the presence of criu.kdat cache file seems reasonable.
Or course, one may unload the needed modules by hands, but
such smart user may as well remove the /run/criu.kdat file :)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Doing kerndat checks on every criu start is way too slow. We
need some way to speed this checks up on a particular box.
As suggested by Andre, Dima and Mike let's try to keep the
collected kdat bits into some tmpfs file. Keeping it on
tmpfs would invaludate this cache on every machine reboot.
There have been many suggestions how to generate this file,
my proposal is to create it once the kdat object is filled
by criu, w/o any explicit command. Optionally we can add
'criu kdat --save|--drop' actions to manage this file.
v2:
* don't ignore return code of write() (some glibcs complain)
* unlink tmp file in case rename failed
v3:
* add one more magic into kerndat_s which is the 'date +%s'
* ignore any errors opening or saving cache. Only size/magic
mismatch matters (and result in dropping the cache)
* cache file path is Makefile-configurable (RUNDIR)
* don't save cache if kerndat auto-detection failed
v4:
* Use ?= for RUNDIR definition.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
v2: When uffd is present, the reported features may still be 0,
so we need one more bool for uffd syscall itself.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Some get_status() methods may allocate data, because
not all of the fields in /proc/[pid]/status file
have the fixed size. For example, NSpid, which
size may vary.
Introduce new method free_status() in counterweight
for such type get_status() methods. it will be called
in case of we go to try_again and need to free allocated
data.
Also, introduce data parameter for a use in the future.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The goal of this function is to compare everything except caps,
but caps size is took to compare. It's wrong, there must be
used offsetof(struct proc_status_creds, cap_inh) instead.
Also, sigpnd may be different too.
v3: Move excluding sigpnd from comparation in this patch (was in another patch).
Reorder fields in seize_task_status().
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Having a "header library" is nice if it's small and clean, but
- we compile its code a few times;
- there is no distinction between internal and external functions.
Let's separate functions out of header and into a .c file.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The function is not included into the library, so having its prototype
there was a shortcut. Move it to a separate include file.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is an auxiliary source file. The corresponding object file was
cleaned, but .d was not. Add it to SRC/OBJ/DEP so the appropriate files
will be cleaned automatically.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
MAKEFLAGS += -r only works for sub-make, and it is not applicable to
the current instance. Since previous commit make is not re-running
itself (after re-reading deps files), so MAKEFLAGS no longer works.
Use one more way to disable built-in rules that stand in our way.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As it was pointed out by our esteemed maintainer (let his light shine),
after my recent changes to test/zdtm Makefiles all dependencies are
regenerated even if we only need to build a single test (for example,
cd test/zdtm/static && make env00).
This was caused by "-include $(DEP)" statement. Make sees that these files
are need to be included, but are missing, and since it knows how to generate
them it goes on to do so.
The solution is to use $(wildcard) function which returns the list of
_existing_ files, and so include will only receive the files that exist.
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
inotify_system_nodel.c is supposed to be a symlink to inotify_system.c,
but somehow the file was committed. This, together with the statement
in Makefile to recreate the file, lead to replacing the file with a
symlink during make.
Remove the file, add the symlink, and remove the Makefile rule.
PS yes, I have checked the files are identical.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When we don't restore any namespaces criu forces tasks to wake
it up two times simply to no-op and wake up tasks back. This
can be optimized by simply omitting the not needed wakeups.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Here's why:
This stage is needed to make sure all tasks have appeared
and did some actions (that are called before restore_finish_stage()).
With this description there's no need in involving criu process
in it, this stage is purely inter-tasks sync point.
Taking into account we do already make root task wait for others
to complete forking (it calls restore_wait_ther_tasks()) we may
rework this stage not to involve criu process in it.
Here's how:
So the criu task starts the forking stage, then goes waiting for
"inprogress tasks". The latter wait is purely about nr_in_progress
counter, thus there's no strict requirement that the stage remains
the same by the time criu is woken up.
Siad that, the root task waits for other tasks to finish forking,
does fini_restore_mntns() (already in the code), then switches
the stage to the next (the RESTORE one). Other tasks do normal
staging barrier. Criu task is not woken up as nr_in_progress
always remains >= 1.
The result is -2 context switches -- from root task to criu and
back -- which gives us good boost when restoring single task app.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Describe what the tasks do during restore and what the
expectations at the sync points are.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Looks like this separate stage is not needed. The scripts
involved in ns restore are synchronized with existing stages
like this:
criu: root task:
ROOT_TASK stage
<appear>
"setup-ns" script
PREPARE_NAMESPACES
prepare_namespace()
"post-setup-ns" script
FORKING
restore_task_mnt_ns()
<everything else>
which seems to be OK.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is wat root task does -- calls prepare_namespace().
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The stage name is what tasks do, not what criu waits for.
When the first stage is started we want the root task to
come up, rather than namespaces to get restored.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Don't set futexes by hands, use the restore_switch_stage
helpers explicitly (for code readability).
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The restore_switch_stage() already waits tasks at the
end, so there's no need in one more waiting.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is used now to close descriptors of mount namespaces
and will be used for network namespaces too.
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is required for cases when we inject a fault in criu restore.
In this case we execute "criu restore" and check that it fails,
then we execute "criu restore" without a fault and check that it passes.
If the first "criu restore" restores only a part of processes,
the second criu can get PID of one of restored processes.
https://github.com/xemul/criu/issues/282
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need compat realization for restorer unmap as after rt_sigreturn()
the task is stopped it 32-bit code and ptrace API doesn't allow
setting x86_64 full registers set to ia32 task.
Generic restorer has now x86-specific __export_unmap_compat()
function, which isn't right.
Clean restorer from x86-related realization.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't need __export_unmap_compat() for !CONFIG_COMPAT in restorer
blob. This preparation will allow to move compatible unmap that's
written in x86 asm from generic restorer blob to arch/x86.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Each `make tags` resulted in running feature-tests.
That's not needed for tags generation.
Don't waste time on tests as we don't compile anything.
Reported-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's pretend that we're doing something ;-D
FWIW: cleaning two lines in the test output:
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
========================== Run zdtm/static/tty03 in h ==========================
make[2]: Nothing to be done for `default'.
Start test
make[2]: Nothing to be done for `default'.
./tty03 --pidfile=tty03.pid --outfile=tty03.out
Run criu dump
Run criu restore
Send the 15 signal to 24
Wait for zdtm/static/tty03(24) to die for 0.100000
Removing dump/zdtm/static/tty03/24
========================= Test zdtm/static/tty03 PASS ==========================
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Right now they all sit in a separate file. Since we
don't support CLONE_SIGHAND (and don't plan to) it's
much better to have them in core, all the more so
by the time we dump/restore sigacts, the core entry
is at hands already.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
HOSTCFLAGS are populated with CFLAGS if they are set from environment:
CFLAGS=-O1 make
But it turns out that =? operator, which sets variable iff it was unset
previously - is recursive expanded operator.
Which means that value of HOSTCFLAGS is evaluated every time it's used.
Which is wrong with the current flaw in Makefile:
1. it assigns HOSTCFLAGS with CFLAGS from environment as recursive
2. it assigns target-related options to CFLAGS such as -march.
3. HOSTCFLAGS are used (with the current code - here they are expanded
from CFLAGS).
Which results in target-related options supplied to host objects building,
which breaks cross-compilation.
Fix by omitting recursive expansion for HOSTCFLAGS.
Still we need to keep $(WARNINGS) and $(DEFINES) in HOSTCFLAGS.
Link: https://lists.openvz.org/pipermail/criu/2017-April/037109.html
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: "Brinkmann, Harald" <Harald.Brinkmann@bst-international.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
DEFINES, LDARCH, VDSO in one place - visually simpler, more terse.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Arch-specific options will be clearer without support checks.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's defined in NMK - don't redefine it.
Remove BTW twice exports and twice definition of $(LDARCH).
Call 64-bit ARM as aarch64.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's keep the same name for 64-bit ARM platform across source.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's call it aarch64 across all CRIU - as I was confused at least once
with arm64 name in NMK and this arch-support check.
Yet allowed to be named arm64, as NMK patch is separated.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I bumped in this myself when I had libc6-dev-i386 installed,
while criu said I didn't. Save other guys'es time, spent
in this place.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Acked-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When restoring w/o namespaces it doesn't make sence to
mount /proc by hands and detach it. We can just use the
host-side one.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When injecting the restorer blob criu parses /proc/self/maps
file to find out the hole for the blob itself. It happens
every time and the maps file for criu is now HUGE (~12k),
so it's much more efficient to use bfd for it rather than
glibc's fopen.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This file is parsed on each start, it's nicer to make it
use bfd engine and save several syscalls and #PFs.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When running criu_dump() with zero pid (self dump) a zombie
from the library is left underneath the running processes
and this zombie is thus written into the images.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This naming is left from the first compatible kernel patches.
At that time to return to 32-bit task rt_sigreturn was used with
a special flag.
Now it's not true anymore, the naming doesn't relate.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Many of sysctl_op-s we have read (or write) single entry.
In current implementaiton this results in two opens and
two closes for each -- open /proc/sys, then open the rest.
It's better to use open_proc() as the latter already have
fd for /proc cached.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Point that ia32 C/R was disabled due to missed packages.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As cr-exec is deprecated-removed, drop ruins.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Each opening of a file results in getpid() call which
is now a pure syscall :( For this particular case this
value is poitless, as log engine already prints pids.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We do this to get real pids of the threads, but sometimes
we just know that value.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Introducing negative options for true / false values. The original
getopt_long parser is kept since it is able to set flag-like values
(instead of setting these values in the switch when it's not needed).
The type of the options needed to be changed to integers for getopt_long
to accept flag-like value settings (as per getopt_long documentation,
the address of integer variable has to be passed).
Corresponding negative options are not added for deprecated options.
This patch is a preparation for the addition of configuration files
(GitHub issue #278). General idea of this feature is to have global
configuration files in /etc/criu.d/ directory and user-specific
configuration files in $HOME/.criu.d/ directory, with the possibility
of specifying a chosen file to be used (default files will be used if
none is specified, or none in case the default ones are not present,
to not break compatibility). The options in configuration files should
be possible to be overriden by the options specified on command line,
hence the negative options addition.
The whole feature of configuration files will remove the need of
specifying all the options on command line, with the possibility of
reusing a file for different use case with only overriding some of the
values specified there.
In case both types of option (negative and positive) are passed, the
later one will be applied -- this works with the philosophy of
overriding the "earlier" options from configuration files.
Changes since v1:
- Describe the --no- option prefix in the beginning of OPTIONS section in
both man page and --help instead of mentioning it at every eligible line
(this also fixes line length issue with --help)
- Fix the accidental removal of check_only case caused by bad rebase
- Use a macro for getopt_long struct option generating instead of additional
defines and hardcoded lines
Signed-off-by: Veronika Kabatova <vkabatov@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When checking for XSAVE availability it makes more sense
to check for OSXSAVE than to check for XSAVE. This way the
check works on systems booted with the 'noxsave' kernel
command-line.
travis-ci: success for zdtm/static/fpu01: check for OSXSAVE instead of XSAVE
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Make this function more generic: we want to do not dup not only
transport socket of parent, but just all service fds, which
were not opened at the moment of clone() in parent. But,
yes, currently it's only transport socket.
travis-ci: success for files: Unify clone_service_fd()
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
So, we've done a HUUGE rework in this release, that's why it's 3.0.
Two biggest changes are:
* Compel library -- the framwork for parasite code injection.
* 32bit x86 support. Note, that it's neither x32 support, not 32-bit
criu. It's purely the ability to dump 32-bit tasks on 64-bit host.
With compel at hands the 'criu exec' is removed.
Main set of kudos go to Cyrill and Dima for this heavy lifting :)
Other things include shutdown-ed UDP sockets, bind-mounts to external
bind mounts, ASAN, extentions to RPC, rework of SysVIPC shmem dump
format and some bugfixes and beautifications in CRIT.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
As for compiling syscalls.S needed syscall-aux.h header,
which is linked with making $(sys-asm-types), add it to deps.
Fixes:
> In file included from compel/arch/aarch64/plugins/std/syscalls/syscalls.S:2:0:
> compel/include/uapi/compel/plugins/std/syscall-codes.h:568:44: fatal error: compel/plugins/std/syscall-aux.h: No such file or directory
> #include <compel/plugins/std/syscall-aux.h>
> ^
> compilation terminated.
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As helper unmaps 64-bit vDSO blob, it can call only raw syscalls.
Also by that reason it's code should be not instrumented with GCOV/ASAN.
Disable instrumentation by separating it into new object and filtering
gcov/asan cflags.
Fixes: #290
@avagin, it rarely reproduces, I failed to reproduce even once
(with gcov, on the same env00 test, with the same linux-next)
please, reopen#290 if you'll spot it afterward.
Reported-by: Andrei Vagin <avagin@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Fixes compile-time errors on Fedora like:
In file included from unlink_fstat01.c:9:0:
> unlink_fstat01.c: In function ‘main’:
> ../lib/zdtmtst.h:123:11: error: format ‘%ld’ expects argument of type ‘long int’, but argument 4 has type ‘__off64_t {aka long long int}’ [-Werror=format=]
> test_msg("FAIL: %s:%d: " format " (errno = %d (%s))\n", \
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Please, see incode comment about the issue.
There was an attempt to fix this feature in kernel:
http://www.spinics.net/lists/arm-kernel/msg258870.html
I'll send a patch for kernel with a correct justification.
Still it's worth to workaround this on older kernels.
mremap() after shmat() makes it possible to C/R shmem between ARMv7 CPUs.
Without it C/R will fail even on the same platform.
That is possible that this workaround changes *restore failure* to
*corruption* in shared memory after restore.
Still, I think it's worth to be applied by the following reasons:
1. All ARMv7 CPUs do not have VIPT aliasing data cache.
And ARMv6 CPUs may have any, but they are not popular because of UMP.
2. SysV IPC shmem should be writable and SHMLBA unaligned
(if it's only readable, then it's OK).
3. For the data corruption we need to migrate from non-VIPT cached CPUs
to VIPT aliasing.
4. As this is shmem migration between platforms - quite likely we have
it`s copy (in case of whole IPC namespace dump - in images).
5. C/R before on the same CPU may fail (quite likely, more than 50% of
zdtm/transition/ipc failed while I've test it).
So, I think it's very unlikely that someone uses CRIU to migrate
from ARMv7 to ARMv6 unaligned writable shmem, but if he is - here is
a BIG WARNING on restore.
And after all: we've restored application as it was on checkpoint,
we can't reliably tell that shmem needs align on the target platform,
but we warned on restoring.
I wanted to test the cpuid for VIPT caching firstly, but it's in cp15
coprocessor, which means it's unavailable from userspace. Only one
reliable way to tell is to check couple of first boot lines in dmesg:
[ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Flag `noexecstack' for ld implies `EXSTACK_DISABLE_X' ELF flag
on CRIU binary. Without this flag the kernel ELF loader will set
`READ_IMPLIES_EXEC' personality bit:
> if (elf_read_implies_exec(loc->elf_ex, executable_stack))
> current->personality |= READ_IMPLIES_EXEC;
This flag is checked by sys_mmap():
> if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
> if (!(file && path_noexec(&file->f_path)))
> prot |= PROT_EXEC;
Which results in each mmap() syscall returning +x mapping for any
readable mapping for CRIU binary, e.g:
Before C/R:
76fc4000-76fc5000 r--p 0001f000 b3:02 131656 /usr/lib/ld-2.25.so
76fc5000-76fc6000 rw-p 00020000 b3:02 131656 /usr/lib/ld-2.25.so
After restore:
76fc4000-76fc5000 r-xp 0001f000 b3:02 131656 /usr/lib/ld-2.25.so
76fc5000-76fc6000 rwxp 00020000 b3:02 131656 /usr/lib/ld-2.25.so
Which also makes ZDTM very sad:
1: Old maps lost: set(["76f80000-76f81000 ['rw-p', '0120400']", "25000-26000
['rw-p', '0120400']", "76f7d000-76f7f000 ['rw-p']", "14a8000-14c9000 ['rw-p']",
"76f4a000-76f4c000 ['r--p', '0120400']", "7ed3d000-7ed7f000 ['rw-p']",
"76f7f000-76f80000 ['r--p', '0120400']", "24000-25000 ['r--p', '0120400']",
"76f4c000-76f50000 ['rw-p', '0120400']"])
1: New maps appeared: set(["76f7f000-76f80000 ['r-xp', '0120400']",
"7ed3d000-7ed7f000 ['rwxp']", "76f4a000-76f4c000 ['r-xp', '0120400']",
"76f80000-76f81000 ['rwxp', '0120400']", "24000-25000 ['r-xp', '0120400']",
"14a8000-14c9000 ['rwxp']", "25000-26000 ['rwxp', '0120400']",
"76f7d000-76f7f000 ['rwxp']", "76f4c000-76f50000 ['rwxp', '0120400']"])
Maybe we also need to set it for arm64 or even for all archs, but that
needs to be tested in the first place, so add it now to arm32, x86
already has it.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Arm32 devices often have poor amount of RAM. E.g., RPI2 board
has only 1Gb memory. This lead to failures with maps01 test,
which tries to mmap() 1Gb of memory. The failures of test is
not very evident - let's document mmap() errors here to
blow some light on the situation.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unix socket name can be a string with any bytes in it. So to
print the name we use base64 encoding. Doing so doesn't allow
to see the socket name when it contains only printable chars.
So here's the custom encoding for bytes fields, that can be
used for custom conversion.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are several places in image files, where we store
integers, but these numbers actually mean some string.
E.g. socket families, states and types and tasks states.
So here's the (criu).dict option for such fields that
helps to convert the numbers into strings and back.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of parsing the output of 'criu -V' this offers a RPC interface
to get CRIU's version. In a follow up patch a test script is included
to use the new interface:
./version.py
Connecting to CRIU in swrk mode to check the version:
RPC: Success
CRIU major 2
CRIU minor 12
CRIU gitid v2.12-635-g6d3ae4d
This change exports the following version fields:
* major
* minor
* gitid (optional)
* sublevel (optional)
* extra (optional)
* name (optional)
The optional gitid field is not set when CRIU is not built from git.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This script connects to 'criu swrk' and asks for the version. If running
from a git checkout the output would look like this:
$ ./version.py
Connecting to CRIU in swrk mode to check the version:
RPC: Success
CRIU major 2
CRIU minor 12
CRIU gitid v2.12-635-g6d3ae4d
If not running from git checkout it looks like this:
$ ./version.py
Connecting to CRIU in swrk mode to check the version:
RPC: Success
CRIU major 2
CRIU minor 12
If running with a CRIU binary which does not support the VERSION
command:
$ ./version.py
Connecting to CRIU in swrk mode to check the version:
Error (cr-service.c:116): RPC error: Invalid req: Success
RPC: Unexpected msg type
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Right now the contents of the sysvipc shmem segment is stored as
raw blob in the ipcns-shm image. This is bad for two reasons.
First is that huge segments with holes are filled with real zeroes
in image. Second is that we prefer not to mix images with pb object
and raw data.
To fix both let's re-use the shmem.c code that keeps anon shared
memory contents in pagemap/pages images.
https://github.com/xemul/criu/issues/287
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After the commit
02c763939c10 ("test/zdtm: unify common code")
CFLAGS with -D_GNU_SOURCE defined in the top Makefile
are being passed to tests Makefiles.
As _GNU_SOURCE is also defined by tests, that resulted in
zdtm tests build failures:
make[2]: Entering directory `/home/criu/test/zdtm/lib'
CC test.o
test.c:1:0: error: "_GNU_SOURCE" redefined [-Werror]
#define _GNU_SOURCE
^
<command-line>:0:0: note: this is the location of the previous definition
cc1: all warnings being treated as errors
make[2]: *** [test.o] Error 1
However, we didn't catch this in time by Travis-CI, as zdtm.py doesn't
do `make zdtm`, rather it does `make -C test/zdtm/{lib,static,transition}`.
By calling middle makefile this way, it doesn't have _GNU_SOURCE in
CFLAGS from top-Makefile.
I think the right thing to do here - is following CRIU's way:
rely on definition of _GNU_SOURCE by Makefiles.
This patch is almost fully generated with
find test/zdtm/ -name '*.c' -type f \
-exec sed -i '/define _GNU_SOURCE/{n;/^$/d;}' '{}' \; \
-exec sed -i '/define _GNU_SOURCE/d' '{}' \;
With an exception for adding -D_GNU_SOURCE in tests Makefile.inc for
keeping the same behaviour for zdtm.py.
Also changed utsname.c to use utsname::domainname, rather private
utsname::__domainname, as now it's uncovered (from sys/utsname.h):
> struct utsname
> {
...
> # ifdef __USE_GNU
> char domainname[_UTSNAME_DOMAIN_LENGTH];
> # else
> char __domainname[_UTSNAME_DOMAIN_LENGTH];
> # endif
Reported-by: Adrian Reber <areber@redhat.com>
Cc: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
v2: Use the devicemapper storage driver for docker containers to
run more tests. AUFS doesn't support file handles, so a few tests
(e.g. inotify00 can't be run).
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In this patch, we replace all zero characters to '@'.
==30==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60300000e3ca at pc 0x7f34144b6be1 bp 0x7ffee7b6bb20 sp 0x7ffee7b6b298
READ of size 26 at 0x60300000e3ca thread T0
#0 0x7f34144b6be0 (/lib64/libasan.so.3+0x8dbe0)
#1 0x7f34144b8e4d in __interceptor_vsnprintf (/lib64/libasan.so.3+0x8fe4d)
#2 0x4966cb in vprint_on_level criu/log.c:228
#3 0x496b64 in print_on_level criu/log.c:249
#4 0x505c94 in collect_one_unixsk criu/sk-unix.c:1401
#5 0x4e7ae3 in collect_image criu/protobuf.c:213
#6 0x462c5c in root_prepare_shared criu/cr-restore.c:247
#7 0x462c5c in restore_task_with_children criu/cr-restore.c:1420
#8 0x7f34132d70ec in __clone (/lib64/libc.so.6+0x1030ec)
0x60300000e3ca is located 0 bytes to the right of 26-byte region [0x60300000e3b0,0x60300000e3ca)
allocated by thread T0 here:
#0 0x7f34144efe70 in malloc (/lib64/libasan.so.3+0xc6e70)
#1 0x7f3413bdb021 (/lib64/libprotobuf-c.so.1+0x6021)
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Using open_proc/fopen_proc/__open_proc is better since
- it uses openat
- it comes with nice error reporting
Let's use it in places where we can. Even if it does not give any
improvements (such as in cr-check.c), error message unification
is good enough reason to do so.
Requested-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
So, in places where we have errno available (and it makes sense
to show it), we want to use pr_perror().
In places where errno is not set/used, use pr_err().
Cc: Dengguangxing <dengguangxing@huawei.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1. No newline (pr_perror() already adds one for you)
2. No colon before file name, e.g.
WAS: Can't open file: /some/file: permission denied
NOW: Can't open file /some/file: permission denied
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Cc: Dengguangxing <dengguangxing@huawei.com>
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unlike pr_perror(), pr_err() does not append a newline.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The contents of sysvshm areas is sometimes dumped twice.
First time it goes via cr_dump_shmem(), since each attachment
of the segment is noted by the add_shmem_area() and thus
gets into the list scanned by the former call().
Second time it is dumped by dump_ipc_shm_pages().
Another thing is that in the 1st dump memory gets into the
standard pagemap/pages image pair, while in the 2nd time
it's all written as plain byte array into ipcns-shm.img.
At restore contents is read from the ipcns-shm.img (2nd).
While the first way is preferred, let's (temporarily)
eliminate it. Historically these segments were dumped and
restored the 2nd way.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When this test is compiled on ARMv7, we get this:
> maps03.c: In function 'main':
> maps03.c:15:31: error: result of '10l << 30' requires 35 bits
> to represent, but 'long int' only has 32 bits [-Werror=shift-overflow=]
> mem = (void *)mmap(NULL, (10L << 30), PROT_READ | PROT_WRITE,
> ^~
Surely, the nature of the test looks like it needs 64-bit addressing.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Make it possible to use a custom message telling why the test is
skipped.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Makefile knows that a binary depends on .o file,
and the .o file depends on .c file, and adds the
per-target variables even in the indirect case.
Therefore, .o suffix is not needed here.
Note that it not hurts to leave it as is, so this commit
is done only for the sake of keeping things simple.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This test name was added by commit 1ce1cca, but there is no test.
We do not use these lists since zdtm.py was introduced, therefore
the error went unnoticed. I found it while running "make dep".
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit expands the success with lib/Makefile to the rest of
ztdm/Makefiles. In particular, it moves the common part to Makefile.inc
and let {lib,static,transition}/Makefile use it.
This results in:
- dependencies being handled properly;
- reduction of makefiles length due to unification;
- possibly more proper dependencies and builds.
While at it, let's also:
- make rules for criu-rtc.so silent;
- set default CC=gcc;
- remove duplicate -m32 from CFLAGS.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In GNU make, 'override' means change a variable even if it was set
from the make command line (as in "make VAR=value"). As we do not
intend to modify CFLAGS/LDFLAGS from the command line, 'override'
can be dropped.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When optimizing our Travis runs, I noticed that test/zdtm/lib is built 3
times in a row -- first time the binaries, 2nd and 3rd time the deps,
in parallel (sic!).
I took a look at Makefile and found this, and some more problems,
like:
- dependencies are generated but not included
- cleandep does not depend on clean
- groups.c dependencies are not generated (or used)
- "make all" does not make groups binary
- overcomplicated and unused groups.{pid,out,cleanout} targets
- extra -f flag to rm
- etc.
This patch (hopefully) fixes all of the above. In addition, it provides
a few enhancements:
- enables "silent make" rules, so now lib/ is in line with the rest of zdtm
- adds "dep" target (not used, just for convenience)
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Commit 299e4b4 ("travis: enable ccache for docker/qemu builds") combined
multiple RUN statements in Dockerfiles into a single one, which is good
for performance (as there is an intermediate cache created after each
statement). Unfortunately, it partially did so by combining statements
with use of semicolons, meaning we are ignoring non-zero exit codes.
As a result, failure from make are ignored and Travis builds are all
green.
To fix, replace all occurences of semicolon with &&.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since commit 93db22b ("compel: no -r for ARM ldflags") and
commit ce043d3 ("compel: make plugins .a archives") the generated
parasite/restorer blobs for 32-bit ARM are no longer relocatable,
and so their ELF header has e_type of ET_EXEC (rather than ET_REL).
As a result, we have "Unsupported header detected" message and
a failure from compel hgen.
This commit allows e_type == ET_EXEC in case NO_RELOCS is defined.
I am not sure if it's OK to still allow ET_REL -- maybe Dmitry
can chime in on that.
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Commit d9486bd720 ("arm/pie/build: do not produce relocatable parasite
object") removed -r from LDFLAGS used to compile criu pie. This
functionality somehow never made it to criu-dev, and was also lost
in master then compel was ported to it.
Make it work with compel.
Unfortunately it was not as simple as I initially thought, as -r flag
to ld was built into nmk. This patch removes it, and adds it to all
places that need intermediate linking.
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The objective is to only do parasite code linking once -- when we link
parasite objects with compel plugin(s). So, let's use ar (rather than
ld) here. This way we'll have a single ld invocation with the proper
flags (from compel ldflags) etc.
There are two tricks in doing it:
1. The order of objects while linking is important. Therefore, compel
plugins should be the last to add to ld command line.
2. Somehow ld doesn't want to include parasite-head.o in the output
(probably because no one else references it), so we have to force
it in with the modification to our linker scripts.
NB: compel makefiles are still a big mess, but I'll get there.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When performing static linking, the order of objects is important
(when the linker finds an undefined reference, it looks forward,
never back). Therefore, sorting objects breaks things.
Required for the next patch.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1. Remove .FORCE, it's not used.
2. Consolidate CFLAGS stripping into a single line.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The way criu/pie/Makefile is currently written, ld is run twice:
1. link $(NAME-obj-y) objects to NAME.built-in.o
2. link NAME.built-in.o, pie.lib.a, and compel plugins
to NAME.built-in.bin.o (with compel ldflags and linker script)
There is absolutely no need for such two-stage linking, but it was OK.
It is not OK now, as "compel ldflags" for ARM doesn't need -r, and we
can't run the first stage with -r and the second stage without it.
So, let's simplify linking using a single ld invocation. This is my
third attempt in doing it, I think I nailed it this time -- it is now
clean and (relatively) simple.
While at it:
- fix compel linker script dependency (it was not working);
- rearrange the Makefile so variables goes first, then rules;
- remove a comment about mount implementation in restorer.
NOTE that compel is called with ./ prefix so the file paths it prints
are also prefixed with ./, which is needed for objectify macro to ignore
those.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1. Remove useless LDFLAGS -- dynamic linker is not used here.
2. Remove $(iquotes) -- there are none defined here.
3. Consolidate filter-out statements into a single one.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is an addition to commit 3a7e027 ("criu: pie -- Switch to use
compel shipped lds scripts").
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There are too many directories in the include path.
Let's remove this one, and refer to the blobs with pie/ prefix.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is a missing hunk from commit 85b04c8 "Makefiles: nuke $(SRC_DIR)"
which has somehow escaped from my attention.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It can be passed as link to real object.
Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Usually we print the PID we wait for, let's do the same here.
Probably just a typo.
Cc: Kirill Tkhai <ktkhai@virtuozzo.com>
Reviewed-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I guess this is a followup to commit 59e80d4.
1 s/determinate/figure out/ (there is no "determinate" verb in English)
2 moved 'with' to the end
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
These helpers are valuable and can be used outside.
Signed-off-by: Stanislav Kinsburskiy <skinsbursky@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Before dump:
438 437 0:51 /mtest /zdtm/static/mnt_ext_manual.test rw,relatime - tmpfs zdtm_auto_ext_mnt rw
439 437 0:51 /mtest /zdtm/static/mnt_ext_manual_private_shared_bind.test rw,relatime shared:144 - tmpfs zdtm_auto_ext_mnt rw
440 437 0:51 /mtest /zdtm/static/mnt_ext_manual_bind.test rw,relatime shared:144 - tmpfs zdtm_auto_ext_mnt rw
441 437 0:51 /mtest /zdtm/static/mnt_ext_manual_slave_shared_bind.test rw,relatime shared:145 master:144 - tmpfs zdtm_auto_ext_mnt rw
442 437 0:51 /mtest /zdtm/static/mnt_ext_manual_slave_bind.test rw,relatime master:145 - tmpfs zdtm_auto_ext_mnt rw
>From log: mount mnt_ext_manual_slave_bind is restored as slave of
mnt_ext_manual_slave_shared_bind, which is restored as slave of
mnt_ext_manual_private_shared_bind, which is restored as shared of
mnt_ext_manual_bind, which is restored as private bind of external,
that is exactly the same way mnt_is_external() looks for external.
v2: fix test to cover all cases in mnt_is_external()
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If container has external bindmount given to criu through
--ext-mount-map option by admin, container user can bindmount
subdirs of these external bindmount to somewhere else inside
container creating secondary external bindmounts. Criu we will
fail to restore them as having unreachable sharing. But we can
restore secondary external bindmounts bindmounting them from
primary external bindmount.
v2: s/external_bind/mnt_is_external/, make mnt_is_external bool,
do mnt_is_external without recursion
v3: add debug message on propagate_mount when bind is set
v5: remove hunk of v4 which goes to previous patch, so same as v3
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
need it to check if we can bindmount from external mount
note: when migrating from criu with patch to criu without,
external mount mapping won't work, we do not support it.
v2: s/real_root/ext_real_root/
v4: add comment
v5: use ext_key field for mapping, put NO_ROOT_MOUNT in root
for old externals for which we do not have it.
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
"return" and "exit" are mixed in this function, and this is wrong.
Must be "return" only, because its callers don't want exit.
Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
mi->external is always false in these places
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
"make uninstall" is supposed to remove all the files that
"make install" (with the same arguments) have created.
This is a test to check that.
PS ideally, "make uninstall" should also remove any empty directories,
but let's not care about it for now.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As we compile-test non-x86_64 architectures under qemu emulation,
it works pretty slow.
Dmitry Safonov suggested, and Andrey Vagin initially implemented
supporting ccache for such builds. This patch is based heavily
on Andrey's work -- all the bugs added are purely mine though.
Performance results: in an ideal environment (two builds of the same
code, one with cold (empty) ccache, another with the hot one)
I saw compile time improvements of 4x to 5x, and total test run time
improvement up to 2x to 2.5x. In layman terms, the complete test run
that was taking more than 50 minutes now takes about 25!
Notes on handling .ccache directory:
1. Before running docker build, .ccache directory (saved in between
runs by Travis) is moved to criu source code root, from where it
is copied by docker together with criu sources.
2. In Dockerfile, .ccache gets moved to /tmp, and CCACHE_DIR
is set accordingly.
3. After running docker build, .ccache is copied out from docker
container back to the host (from where it is saved by Travis).
Ccache envorinment notes:
1. CCACHE_NOCOMPRESS is needed because otherwise tons of time is spent
on compression/decompression (big performance hit under qemu).
2. CCACHE_CPP2 is required with clang, see detailed explanation at
http://petereisentraut.blogspot.com/2011/09/ccache-and-clang-part-2.html
The logic of setting CCACHE_CPP2 in Dockerfile is somewhat fancy;
unfortunately I was not able to come up with a simpler approach.
Misc:
1. Travis runs "ccache -s" after the build is completed. A call to
"ccache -s" is called to Dockerfile before make, so one can
compare before/after numbers.
2. make invocations are surrounded by "date" calls so one can get the
compilation times.
Changes in v2:
- consolidate Dockerfile statements (ENV, RUN)
- single object make test is no longer commented out
- simplify "make mrproper" test
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For compatibility with ccache (so it can cache the compilation results),
let's compile and link separately. For this, we have to
- disable the implicit make rules
- write the explicit ones
While at it, do use the "silent make" stuff that is already here
FIXME: figure out if it helps to speed up ccache build
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For now, it's done for local builds only (i.e. no per-arch Docker
builds yet). The reason is, it's easier to play with ccache when
the compiles are (relatively) fast.
Performance: there is 2x to 3x improvement in build speeds for
ideal cases (same code, hot cache), but the absolute savings
are negligible (example: 7 seconds instead of 23).
Note that ccache is not compatible with gcov, so we only enable it
for non-gcov build (which happens to be the one with clang).
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Unify alpine and non-alpine builds. The only difference is foreign
arch builds need some preparation -- separate that to a dependency.
Unfortunately we can't use wildcard targets ("%: ") as non-wildcard
ones are prevaling. Therefore, a somewhat ugly hack to generate
$arch: Dockerfile.$arch dependency is added.
While at it:
- rename DB_ARGS to DB_CC
- mark clean as phony
- make "all" really run all the builds we can
Nice side effect: autocompletion ("make -C scripts/build <TAB>")
now works!
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As pointed out by Andrey, arch clang tests are using gcc regardless
of CLANG=1 set in travis environment.
Frankly, I do not understand how it worked before (while being
pretty sure it worked!), but here is a way to fix it.
Reported-by: Andrey Vagin <avagin@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is generated by clang-3.8:
> compel/arch/ppc64/src/lib/infect.c:31:20: error: unused function
> '__check_code_syscall' [-Werror,-Wunused-function]
> static inline void __check_code_syscall(void)
> ^
The fix is the same as in commit 3ea2fd7.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
If using the '--keep-going' option, zdtm prints out an overview how many
tests were run, failed and skipped. This would also be useful to know if
it did not fail. This patch changes the output like this:
################## ALL TEST(S) PASSED (TOTAL 297/SKIPPED 36) ###################
or in the case of a failure it is unchanged:
################### 2 TEST(S) FAILED (TOTAL 297/SKIPPED 34) ####################
* zdtm/static/sched_policy00(ns)
* zdtm/static/cgroup02(h)
##################################### FAIL #####################################
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
decode_flav() was doing 'if i in flavors:' where 'i' was an integer but
the keys from the flavors dict are strings 'h', 'ns' and 'uns'.
Signed-off-by: Adrian Reber <areber@redhat.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When infecting victim we construct sigframe to
be able to self-rectore it in case if something
goes wrong. But in case is a targer been using
alternative stack for signal handling it will
be missed in sigframe since we don't fetch it.
Thus add fetching sas on infection stage and
put it into signal frame early.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to leave this part of restorer in restored task in case
of inserted redirected calls. Jump trampolines from old vdso lead
here - it would be painful to land nowhere.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reworked this code a little and it becomes more readable.
Drop those macroses under CONFIG_X86_64 define and just use
boolean `compat_vdso' to check whether insert 64 or 32-bit jmp.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's the same on all archs (as it's called from generic code),
no need to redeclare it. <parasite-vdso.h> is included in all
per-arch headers. Drop vdso_symtable forward declaration as
<parasite-vdso.h> includes <util-vdso.h> header which defines
the structure.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When checkpointing applications with really big
memory slab (like in our vz7 test with 920G of
memory) the int type get cutted, we should use
long int instead, just like we do in other code
pieces.
Otherwise get (on vz7's criu, which s sharing the code)
| pie: 756: Daemon waits for command
| (01.193097) Wait for ack 12 on daemon socket
| (01.193112) Fetched ack: 12 12 0
| (01.193164) 988065 fdinfo 0: pos: 0 flags: 100002/0
| (01.193201) fdinfo: type: 0xb flags: 0100002/0 pos: 0 fd: 0
| (01.193279) 988065 fdinfo 1: pos: 0 flags: 100002/0
| (01.193307) fdinfo: type: 0xb flags: 0100002/0 pos: 0 fd: 1
| (01.193341) 988065 fdinfo 2: pos: 0 flags: 100002/0
| (01.193365) fdinfo: type: 0xb flags: 0100002/0 pos: 0 fd: 2
| (01.193375) ----------------------------------------
| (01.193405) Error (criu/parasite-syscall.c:243): BUG at criu/parasite-syscall.c:243
| pie: 756: Error (criu/pie/parasite.c:676): Trimmed message received (1>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Supporting shutdown for dgram sockets (udp and udplite)
is simple -- just fetch the state from diag module and
record it in the image, then upon socket creation restore
this state.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To restore fsnotify's watches on files we need to find paths for each
of them using handle we have in /proc/<pid>/fdinfo/<fsnotifyfd>.
These handle is valid to open the file with open_by_handle_at if
you have mount fd where the file lays. So we try open_by_handle_at
for all possible mount fds we have.
But we can not do so for 'file' bind-mounts, as the way we open
mount fd opens file instead and can hang on fifos or fail on sockets.
(see check_open_handle->open_handle->open_mount code path, imagine
lookup_mnt_sdev() found 'file' bind-mount, open_mount() failed(hanged)
in __open_mountpoint() and if irmap_lookup() also was not successful the
whole dump fails too)
So if we have file bindmount of fifo file, and we restore some
inotify on other file on other mount with same s_dev, we hang forever
on open.
So just skip non-directory mounts from inotify search we will find
path for them on other mount(e.g. non-bindmount) with same s_dev.
v2: remove isdir hashing, improve commit message
v3: make lookup_mnt_sdev handle only nondir mounts, add comment,
move more expensive notdir_mountpoint check after s_dev
v4: inverse notdir_mountpoint to be mnt_is_dir, now on error
in mnt_is_dir mount is also skipped
Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
External mounts are provided by an user and CRIU doesn't
need to restore their content.
https://github.com/xemul/criu/issues/299
Reported-by: Stéphane Graber
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we collect mounts to clean up a mount namespace,
but it isn't required when we are going to call pivot_root.
https://github.com/docker/docker/issues/31663
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
An example, that steals stderr descriptor from victim task.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is just export by reasonable name of the existing
code, that sends and receives FDs via compel RPC socket.
v2:
Rebase on recent criu-dev
Fix parallel build
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 73371 (#1 of 1): Big parameter passed by value (PASS_BY_VALUE)
pass_by_value: Passing parameter regs of type user_regs_struct_t
(size 224 bytes) by value.
Suggesting to do this until compel is released and API is cut in stone.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Found by Coverity error:
> CID 172193 (#1 of 1): Bad bit shift operation (BAD_SHIFT)
> 1. large_shift: In expression 1 << sig % 64, left shifting
> by more than 31 bits has undefined behavior. The shift amount,
> sig % 64, is as much as 63.
That is:
1. yes, UB
2. while adding a signal to mask, this has flushed all other
signals from mask.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The purpose is to unblock previously blocked SIGCHLD, not all the
signals. IIRC, this block-unblock dancing is about a race where SIGCHLD
may come during switching to restorer blob, where CRIU handler function
is already unmapped - which will result in segmentation violation if
SIGCHLD wasn't blocked.
Fixes:3a61c38a5832 ("restore: block sigchld to remap task_entries")
Cc: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The statement like
#include <compel/plugins/plugin-std.h>
looks a bit tautological. I think the single "plugins" word is enough:
#include <compel/plugins/std.h>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
First, for building compel plugins, we already have
"-I compel/include/uapi" in ccflags and asflags, so there is
no need to add "-iquote include/uapi".
Second, let's refer to compel plugin uapi includes in a uniform way,
choosing the same way the external code does, i.e. #include <compel/...>.
Third, in a few cases simplify #include statements by including
compel/plugins/plugin-std.h instead of a number of plugins/std/*.h files.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This header should have everything we have in std/
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
* install
'cp' can copy recursively, create directories, and even
dereference symlinks. Everything we have in uapi/ is to be installed.
NOTE we can't use -r for compel includes, as there is some extra stuff
in there we don't want to take with us (in particular, plugins/
and 'compel -> .' symlinks).
* uninstall
rm -rf everything under compel includedir
While at it, fix some minor things here and there.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It is not used anywhere, so unless someone has any plans, let's kill it.
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
A slash after a directory was missing in a number of places, that
resulted in "make uninstall" leaving a number of files behind.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
GNU make tries to rebuild any makefiles it uses. While in general it's
a good idea (and it is used e.g. in autoconf-based builds), in our case
it is not necessary, as all the makefiles are static.
More to say, as we have a few "match anything" rules for subdirectories,
Makefiles in these subdirs are also matching these rules, which leads to
excessive (re)building while a particular makefile is needed.
Protect such Makefiles with explicit (or pattern) rules, so make knows
it should do nothing to rebuild those.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Apparently @true was used as a rule for any target which should have
a non-empty rule doing nothing. For this, there's a "<target>: ;"
syntax, let's use this and eliminate an unnecessary fork/exec :)
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Mostly this is done in order to not repeat the recursive clean
lines twice.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As all builds are done from top source dir, there is no need
to have SRC_DIR.
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Our whole system of Makefiles are integrated from top to bottom,
meaning:
1. The paths in sub-makefiles are relative to the top source dir.
2. Sub-makefiles are executed via make $(build)=<SUBDIR> <TARGET>
For some reason, makefiles under lib/ are the exclusion. Let's fix it.
Side effect: you can now build any individual target under lib/,
for example, "make lib/c/libcriu.so" works.
[v2: use the .FORCE, thanks to dsafonov@]
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As compel is an external tool now, let's treat it as such -- remove the
hardcoded paths to compel files, they are now provided via compel CLI.
Details:
1. The compel std plugin dependency is dropped from the intermediate
criu/Makefile. It was there in order to make sure plugin is built before
pie, but the top level Makefile and Makefile.compel take care about it.
2. The compel std plugin logic is simplified in criu/pie/Makefile.
3. The compel linker script dependency is kept as-is for now (except
the linker script file name no longer appears in the list of objects
to link).
4. Linking of compel std plugin is moved to a second linking stage
in order to simplify the Makefile.
Side note: we can actually avoid running the linker twice!
5. The compel binary dependency is dropped from criu/pie/Makefile
as this is already there in top-level Makefile (look for criu-deps).
[v2: reworked after dsafonov@ comments; keep most compel deps]
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To check that jump trampolines to rt-vdso works.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reduce __export_restore_task(), which is fat and too long,
drop needless parameter from vdso_proxify() and drop also
that find-tuple logic, which isn't needed really.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's always "dumpee" and is used in two pr_err() messages,
put it right there.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We should log whom we're remapping, but ~5 lines upper or so
we've unmapped dumpee vdso and vvar. Here we're mremapping runtime
host-provided vdso/vvar blobs to the dumpee position.
Correct the messages to reflect that we've remapped rt-vdso/vvar,
having the same naming as in vdso_do_park().
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For 32-bit at this moment there are follwing entries:
o __vdso_clock_gettime
o __vdso_gettimeofday
o __vdso_time
o __kernel_vsyscall
o __kernel_sigreturn
o __kernel_rt_sigreturn
So, there isn't __vdso_getcpu(), which is present in 64-bit vDSO,
and 64-bit vDSO doesn't have those __kernel_*.
This is fine as two vdso blobs with the same not present symbols
are considered to be the same in comparison.
I didn't introduce ARCH_VDSO_SYMBOLS_32, as it would have different
size and that will result in quite painful conversion of struct
vdso_symtable (it's fixed size and e.g., inside parasite's parameters)
Which is not needed by the described behavior of vdso blobs comparison.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Forward CRIU's log fd into helper, so it can actually print errors.
This will help to debug troubles with helper, like #273.
Log fd can be safely written to, as it's opened in CRIU with
O_APPEND or it's line-buffered (stdout) or not buffered (stderr)
stream. Anyway, it's double safe, as there is simple synchronization
between helper and CRIU, so only one of them will log at a time.
Also expanded the comment about a helper.
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This macro is not in use since mid-2012 (commit 4806e13
"protobuf: Convert vma_entry to PB format v3"), so I guess
it is about time to retire it.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's rename the printing functions so their names look more like
the standard ones.
1. putc/puts with a file descriptor.
__std_putc -> std_dputc
__std_puts -> std_dputs
There are no standard putc/puts that accept fd as an argument,
but the libc convention is to use d prefix for such. Therefore:
NOTE we keep the order of the arguments intact, to be in line
with the rest of the functions.
2. *printf
__std_printk -> std_vdprintf
__std_printf -> std_dprintf
The reason is, these are the names of libc functions with similar
functionality/arguments.
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This function works like printf, and it helps the compiler
to know that, so it can check whether arguments fit the
format string.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This function works like printf, and it helps the compiler
to know that, so it can check whether arguments fit the
format string.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
These are part of compel UAPI so should be prefixed with COMPEL_
in order to not pollute the namespace. While at it, move from
set of defines to an enum, which looks a bit cleaner.
Also, kill LOG_UNDEF as it's not used anywhere.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Those macros look twice as long as they should be on my 80-columns
terminal. As there is nothing here to justify such width, go ahead
and remove the extra tabs, keeping the code within 80 cols.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We support compat mode now (at least partially) so
the test should be allowed.
Acked-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To support ia32 compat mode on x86-64 we need to things
- extend fpu_state_t type to carry ia32 specifics
- fill up additional members in fpu_state_ia32_t type
before calling sigreturn (this also requires the
uc_mcontext::fpstate won't be aligned on 32 bytes)
Because we touches base types in compel the criu
has been updated accordingly.
Acked-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In compat mode the fpu frame won't be aligned on 32 bit
due to kernel specifics.
Acked-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It was never functional neither we plan to support
native ia32 mode, so drop these incomplete code
pieces out.
- Presumably we will need TASK_SIZE for compat
mode so I provide TASK_SIZE_IA32 for this sake
- 32 bit syscalls are remaining for a while
Acked-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's now obsoleted by compel library.
Maybe-TODO: Add compel tool exec action?
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the difference between two commits
criu-dev/b0f6f293/Unify own memcpy/memset/memcmp
master/0367a1fe/Drop prefix from own memcpy/memset/memcmp
that makes criu-dev after rebase on master with latter commit
be the same as it was with former commit before rebase.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
First, TASK_* defines provided by compel should be prefixed
with COMPEL_. The complication is, same constants are also used
by CRIU, some are even writted into images (meaning we should
not change their values).
One way to solve this would be to untie compel values from CRIU ones,
using some mapping between the two sets when needed (i.e. in calls to
compel_wait_task() and compel_resume_task()).
Fortunately, we can avoid implementing this mapping by separating
the ranges used by compel and criu. With this patch, compel is using
values in range 0x01..0x7f, and criu is reusing those, plus adding
more values in range 0x80..0xff for its own purposes.
Note tha the values that are used inside images are not changed
(as, luckily, they were all used by compel).
travis-ci: success for compel uapi cleanups (rev2)
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
infect.h includes compel.h, and compel.h includes infect.h.
Surely, due to include guards it will be sorted out, but
we'd rather just include what we need.
travis-ci: success for compel uapi cleanups
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We have ptrace defines and functions that are part of UAPI,
and we have some internal stuff not to be exposed. Split
ptrace.h into two files accordingly.
While at it, do some cleanups:
- add ptrace_ prefix to some functions and macros
- remove (duplicated) PTRACE_* defines from .c files
- rename ptrace_seccomp(), remove its duplicate
- remove unused ptrace defines
- remove unneeded (ptrace-related) includes
travis-ci: success for compel uapi cleanups
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To run CRIU with ASan we have to use some non-default options:
- detect_leaks=0 - We have to many leaks for know. Let's disable until fixed.
- disable_coredump=0 - without this ASan library changes RLIMIT_CORE which
break rlmimits00 tests.
- log_path=asan.log - For some reason default output to stderr sometimes
doesn't work in CRIU. So error log will be stored
in asan.log.<pid> file instead.
travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
ASan doesn't play nicely with clone if we use current stack for
child task. ASan puts local variables on the fake stack
to catch use-after-return bug:
https://github.com/google/sanitizers/wiki/AddressSanitizerUseAfterReturn#algorithm
So it's become easy to overflow this fake stack frame in cloned child.
We need a real stack for clone().
To workaround this we add clone_noasan() not-instrumented wrapper for
clone(). Unfortunately we can't use __attrbute__((no_sanitize_addresss))
for this because of bug in GCC > 6:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69863
So the only way is to put this wrapper in separate non-instrumented file.
travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This allows to build criu with AddressSanitizer enabled:
make ASAN=1 -j<N>
travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
This adds the reverse of CFLAGS_obj.o with CFLAGS_REMOVE_obj.o.
This allows to prevent certain CFLAGS from being used to
compile files.
travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We don't need gotpcrel inside parasite's blob:
we handle relocations over remote map in compel library,
reading them from parasite's blob header.
travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
We need to copy only parasite, do copy page-aligned size,
which will copy part of CRIU binary, that follows parasite
blob. That will cross red-zones and fire asan error.
travis-ci: success for series starting with [1/6] compel/infect: fix out-of-bounds parasite memcpy()
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Those symlinks were for building 32-bit objects with `-m32` to
link them with 32-bit parasite. Since I have dropped second parasite,
I cleaned Makefile rules for 32-bit parasite, but accidentally left
those symlinks. Drop them now.
travis-ci: success for x86/compat: clean symlinks left from second parasite
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The functions it provides, send_fds() and receive_fds(), are already
provided by compel/plugins/std.built-in.o (compel/plugins/std/fds.c)
which is linked into both parasite and restorer.
This fixes the following issue (for some reason, reported on ARMv7,
see https://travis-ci.org/kolyshkin/criu/jobs/195367825):
LINK criu/pie/parasite.built-in.o
GEN criu/pie/parasite.built-in.bin.o
criu/pie/pie.lib.a(util-fd.o): In function `send_fds':
/criu/include/common/scm-code.c:56: multiple definition of `send_fds'
criu/pie/parasite.built-in.o:/criu/include/common/scm-code.c:56: first
defined here
criu/pie/pie.lib.a(util-fd.o): In function `recv_fds':
/criu/include/common/scm-code.c:79: multiple definition of `recv_fds'
criu/pie/parasite.built-in.o:/criu/include/common/scm-code.c:79: first
defined here
criu/pie/Makefile:53: recipe for target
'criu/pie/parasite.built-in.bin.o' failed
make[2]: *** [criu/pie/parasite.built-in.bin.o] Error 1
travis-ci: success for criu/pie: kill util-fd.c
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In a manner similar to one of commit 9303ed3 ("Makefiles: move
-Wa,--noexecstack out of CFLAGS"), let's move this option
from assembler to linker flags (see the abovementioned commit
for reasoning).
This fixes generating dependencies for criu/arch/x86/call32.S when using clang:
DEP criu/arch/x86/call32.d
clang-3.8: error: argument unused during compilation: '-Wa,--noexecstack'
DEP criu/arch/x86/call32.d
clang-3.8: error: argument unused during compilation: '-Wa,--noexecstack'
travis-ci: success for criu/arch/x86/Makefile: move -Wa out of asflags (rev2)
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The kernel does touch only relevant union member on x86_32.
travis-ci: success for zdtm/sigpending/32: check only 12 bytes of _si_fields
Cc: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's library plugin to CRIU - it needs to be 64-bit.
travis-ci: success for zdtm/test/rtc: build 64-bit criu-rtc.so
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For 32-bit fcntl() Glibc function calls sys_fcntl64(), which
needs struct flock64, otherwise the kernel gets a wrong struct.
For 64-bit, it's all the same.
Also unset errno before fcntl() and check return value of the call.
Cc: Qiang Huang <h.huangqiang@huawei.com>
Cc: Begunkov Pavel <asml.silence@gmail.com>
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
travis-ci: success for test/zdtm: use flock64 instead of flock
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Raw sys_mmap() returns address or error like -ENOMEM.
Don't check MAP_FAILED, check that result is aligned by page.
travis-ci: success for x86/compat: fix error-check for compat mmap()
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Initialy, I thought to name it "compat_restore", but after I've dropped
the second 32-bit parasite (which surely made compat code lesser and
easier), our parasite works in 64-bit in 32-bit task and ptrace()
for setting registers in this long-jumped situation will work correctly
only after v4.9 kernel. Maybe it can be work-arounded if needed,
but yet no compatible dump for pre-v4.9 kernels.
Requested-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As threads restore in parallel, stack32 may be reused concurrently
leading to reusing others thread's data. So, let it lay on stack.
It would still worth making 32-bit stack per-task reusing it in threads
but at this moment introducing such complexity looks like premature
optimization.
It does not affect 64-bit C/R.
Fixes: file_aio, sigaltstack, clone_fs, socket_aio, different_creds, futex
travis-ci: success for 32-bit tests fixes
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's a workaround to clang-3.4, which doesn't handle numbers
in asm macros rightly:
https://llvm.org/bugs/show_bug.cgi?id=21500
Which resulted in:
CC compel/arch/x86/plugins/std/parasite-head.o
<instantiation>:3:2: error: too few operands for instruction
pushq
^
compel/arch/x86/plugins/std/parasite-head.S:26:2: note: while in macro instantiation
PARASITE_ENTRY
^
Fixes: https://travis-ci.org/0x7f454c46/criu/jobs/186099057
travis-ci: success for 32-bit tests fixes
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise we'll try to set 32-bit register set to 64-bit task,
which is not possible with ptrace - it uses register set size,
according to processes mode. So we should set 32-bit regset
only to tasks those are in 32-bit mode already.
Please, see inline comment in the patch for more info.
travis-ci: success for 32-bit tests fixes
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We can be on v4.9 or newer kernel, but have no 32-bit multilib
toolchain, which will result in !CONFIG_COMPAT but
kdat_compat_sigreturn_test() will return true as we have
new arch_prctls in kernel needed for compatible C/R.
Fail compat test in this case.
travis-ci: success for 32-bit tests fixes
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As I've united k_rtsigset_t between native and compat ucontext's,
it's 8-bytes aligned now. We don't care about align of this as
we fill it always with memcpy()/memset(0).
So after those changes, ucontext_ia32 has received new padding
between uc_mcontext and uc_sigmask (4 bytes to align to 8-byte sized
sigmask). Because of this, mask of blocked signals was restored
with shift (wrongly).
Fixes: signalfd00, file_attr tests.
travis-ci: success for 32-bit tests fixes
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In this case it will work for any make commangs. For example:
make COMPAT_TEST=y -C test/zdtm/lib
travis-ci: success for zdtm: handle COMPAT_TEST from Makefile.inc
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Problem: if we do
touch criu/arch/x86/cpu.c
nothing is being rebuilt.
For detailed analisys, see the previous commit
("criu/Makefile: fix rebuilding criu/pie/pie.lib.a").
Note there are other targets in criu/Makefile where one
might want to add .FORCE to, but it's not needed as they
all depend on another target which itself is marked as .PHONY.
travis-ci: success for Makefiles: fix deps checking
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As reported by Andrei Vagin:
touch criu/pie/parasite-vdso.c
does not lead to rebuild pie.lib.a and its dependencies.
This happened because the real dependencies of criu/pie/pie.lib.a
are listed in criu/pie/Makefile.library, which is never included
or called with sub-make, because the criu/Makefile says:
criu/pie/pie.lib.a: $(ARCH-LIB)
$(Q) $(MAKE) $(call build-as,Makefile.library,criu/pie) all
essentially saying we only need to call a sub-make with Makefile.library
if the target is absent, or $(ARCH-LIB) is newer than the target.
A workaround is to use .FORCE so that the Makefile.library is always
called and so the dependencies are checked.
Note the above is also true for any target that involves calling
a sub-make -- it should either be used with .FORCE or otherwise
depend on a phony target. I haven't checked all the CRIU makefiles
but suspect there might be more cases like this one.
travis-ci: success for Makefiles: fix deps checking
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
travis-ci: success for .gitignore: Add compel and common asm symlinks
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Yet another nail in the coffin of compel cli usage complexity.
Since commit cd1c9d9 ("compel: simplify usage wrt ids") landed,
it became obvious that the newly introduced -p option can be
made optional. First, prefix value is not very important;
second, it can be easily generated from the input (or output)
file name.
This is what this commit does, also trying to check that
the resulting prefix is adeqate for using in C code. In case
it is not (say, file names used are 1.po 1.h), an error
is printed, suggesting to use --prefix.
The commit also makes use of this functionality by removing
-p option from compel/test/infect and criu/pie Makefiles.
While at it, let's also remove -l 4 and the kludge of hiding it.
If the output generated by this is ever needed, one can easily
run "compel hgen -l4 ..." manually.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Add "compel libs" that prints the list of libraries needed
to link the parasite loader.
Make compel/test/ and criu/ to use it.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
A compel user should not be aware of compel internals, including
the paths to various files. This commit introduces a command to
get the plugin files (well, currently just one plugin, "std").
Example for uninstalled compel:
$ cd compel/test/infect/
$ ../../../compel/compel-host plugins
../../../compel/plugins/std.built-in
Example for installed compel:
$ compel plugins
/usr/libexec/compel/std.built-in.o
The commit also makes use of this command by compel/test/infect
and criu/pie.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Commit 8173ea2 ("compel/test/infect/Makefile: don't add .h to sources")
was a bad one as it removed dependency between parasite.h and spy binary.
Fix it.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Since commit 656710e the list of prerequisites are the same
as the list of objects, so we can use $^ to avoid repetition.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
compel tool doesn't need to be run as root, so it makes no sense
to install it to SBINDIR. Fix to use BINDIR.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This commit adds -T path/to/linker_script to the output
of "compel ldflags", so compel user does not have to specify
one manually.
This commit also makes use of this functionality in criu/pie
and compel/test.
NOTE this commit also drops the linker script dependency
in criu/pie/Makefile, meaning if it will be changed that
won't cause a rebuild. I hope it's not a big issue, and it is
sort of inevitable as compel is becoming a separate tool.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of hardcoding the path to compel uapi includes,
call compel tool to get one.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Build of criu binary depends on many other things that needs to be built
before it. Let's clean these deps a bit by using criu-deps variable.
This also removes wrong "$(VERSION_HEADER): include/common/asm"
dependency -- one can certainly succeed in generating
criu/include/version.h file without creating include/common/asm
symlink fist!
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Working on CRIU Makefilest feels like walking on a minefield.
This is not an attempt to demine it, but to make some mines
a bit easier to notice.
OK, this is what we're trying to do here:
1. Drop the $(SRC_DIR)/ prefix from the target: as this is a top-level
Makefile, we can just use paths relative to top-level source dir.
2. Drop the $(SRC_DIR) from the symlink, use relative one. Relative
symlinks are always better -- say, if a source directory is
moved, everything will still work.
3. The "compel/include/asm: compel/arch/$(ARCH)/src/lib/include"
dependency is useless. Yes, the left side is created as a symlink
to the right side, but that doesn't mean that "make" should
compare the timestamps of both to decide whether to remake
the target.
4. The "$(COMPEL_VERSION_HEADER): compel/include/asm" dependency
is wrong, the compel/include/asm symlink is not needed for
$(COMPEL_VERSION_HEADER) generation. Remove it.
5. Move compel/plugins/std.built-in.o prerequisite from the rule
to compel-plugins variable, and use it.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Similar to the previous commit, there is absolutely no need
to create/remove this symlink from Makefiles, as it can be
made a constant one. Add the symlink to sources and save
a few lines in Makefiles.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There is absolutely no need to create/remove this symlink
from Makefiles, as it is constant. Just add the symlink to
sources and save a few lines in Makefiles.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As of commit 3c16dc5 ("compel: plugins -- Merge fds plugin into std")
fds plugin is no more. Remove this leftover.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We call compel-host binary from a number of places, so
let's add COMPEL_BIN variable and use it.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I have noticed compel/plugins/include[/uapi] is not needed,
not entirely sure why (added symlinks?) but everything
compiles just fine without it.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1. Add "compel includes" command, to be used for parasite *loading*
code compilation.
2. Add includes to output of "compel cflags", which is used for parasite
code compilation.
Now, this patch looks big and complex, this is mostly because we want
compel cli to work for both uninstalled (right from the source tree)
and installed cases. The paths to be printed are quite different for
these two cases, so I had to introduce a wrapper for a non-installed
case. The wrapper sets an environment variable, which compel binary
uses as a path to non-installed file. If this env var is not set,
it means compel is installed so no tricks are needed.
Note the wrapper is only provided for the compel-host binary, as compel
(which differs from compel-host in case of cross-compiling) is not
executed from within the source tree.
Because of the wrapper, the original binary had to be renamed, thus the
changes to Makefiles and .gitignore.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is mainly dictated by the fact that we use stdout
from "compel *flags" in a special way, so it should not
be garbled by the usage info.
Otherwise, for example, the following code in Makefile
CFLAGS += $(shell compel --badopt cflags)
will lead to the whole usage() output to be added to compiler flags,
which looks really really weird.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There is no need to support all possible architectures
for "compel cflags" action. In fact, "compel hgen" can
only support the one it was compiled for (with the only
exception of 32-bit mode for x86).
It looks like if we can use a few #ifdefs, there is
no need to specify --arch anymore, let's drop it!
Still, for the x86 32-bit mode we need to introduce
--compat option. Note that "compel hgen" autodetects
32-bit mode for x86 by looking into ELF header, but
in case of "compel clfags" there are no files to look
into, so we need this --compat specified explicitly.
While at it,
- Makefile: define CONFIG_AARCH64 if building for ARM64
- fail to compile on unsupported/unspecified ARCH
- make "compel --help" output a bit more compact
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1 Since all the fields are now initialized to zeroes,
we can just say ={};
2 Since this is static, it is initialized to zeroes anyway,
but from my POV being explicit about it is better.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I saw this line in the code
unsigned long sret = -ENOSYS;
and ended up with this patch. Note syscall(2) man page says return value
is long -- who am I to disagree?
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
1. Remove COMMON_IDIR -- there's no need for it, and it makes
the build process look more complicated than it is.
2. Use standard CC and CFLAGS defines (so one can use say make CC=clang)
3. Drop the dependency on COMPEL_LIBRARY, as it's supposed to be
an external file/tool.
4. Add -Wall to CFLAGS.
5. Simplify ARCH setting in infect test.
6. Drop ARCH from rsys test, as it's not used there.
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
travis-ci: success for More polishing for compel cli
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I managed to forgot that kernel erases R8...R11 regitster
prior returning to userspace from `int 0x80`:
https://lkml.org/lkml/2009/10/1/164
That was the reason for hang on gcc v6.1 on Jenkins/elsewhere:
https://ci.openvz.org/job/CRIU/job/CRIU-x86_64/branch/criu-dev/
Tested on gcc v6.1 locally, on Travis-CI:
https://travis-ci.org/0x7f454c46/criu/builds/183976899
travis-ci: success for pie: fix clobber registers for int 0x80 (rev2)
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Tested-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Resolves merge conflict with commit 71abfb84e158 ("compel: simplify
usage wrt ids").
Sets start ip for parasite blob according to app mode: native/compat.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Supported only from v4.9 kernel :)
The following commits may be backported if needed:
b059a453b ("x86/vdso: Add mremap hook to vm_special_mapping")
e38447ee1 ("x86/vdso: Unmap vdso blob on vvar mapping failure")
576ebfefd ("x86/vdso: Replace calculate_addr in map_vdso() with addr")
2eefd8789 ("x86/arch_prctl/vdso: Add ARCH_MAP_VDSO_*")
90954e7b9 ("x86/coredump: Use pr_reg size, rather that TIF_IA32 flag")
cc87324b3 ("x86/ptrace: Down with test_thread_flag(TIF_IA32)")
684635105 ("x86/signal: Add SA_{X32,IA32}_ABI sa_flags")
ed1e7db33 ("x86/signal: Remove bogus user_64bit_mode() check from
sigaction_compat_abi()")
The required patches list may be checked also at
https://criu.org/Upstream_kernel_commits
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's 32-bit syscall and the high-part of address is dropped,
so call it only on 32-bit addr.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As 64-bit parasite is now in 32-bit compat app and
64-bit applications can also have TLS in GDT - simplify and
just always dump TLS with 32-bit syscall get_thread_area,
it's 3 syscalls more - but that's a low cost for that.
Note that entry point for sys_get_thread_area() is only for 32-bits,
so we need to call raw int80 here with 32-bit syscall number.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
More reliable way to check support of mapping 32-bit blob.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We can live here without 32-bit CS - this syscall doesn't depend on
descriptor type.
No functional changes expected, cleanup.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Parasite is 64-bit and if we want to check if vma is vDSO,
we need to link parasite blob with util-vdso-elf32.
But luckely, there is no need to do that: mremap() for
compat vDSO works only after v4.8 kernel:
commit b059a453b1cf ("x86/vdso: Add mremap hook to vm_special_mapping").
And in those kernels "[vdso]" is always reported in /proc/.../maps
rightly - so no need to check that.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
No need to fill symtab at restorer - previous commit add vdso filling at
startup: on vdso_init().
Now it's possible just to use the symtab and sizes if we need them.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Adds a helper to parse compatible vdso blob at time of vdso_init().
The following patches will remove parsing vdso in restorer.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The next patch will remove filling in restorer rt symtable
for compat tasks.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I'll need to validate compat vdso/vvar positioning in the same way.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to know compatible vdso/vvar sizes, so add pid argument
to parse another process - it's needed to fork(), remap vdso
and parse child's vdso/vvar in CRIU.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
On first versions of x86 compat patches it returned 0 or err.
In merged version it returns error < 0 or vDSO blob's size.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Oh, thanks god - those silly crippy macro are gone!
The best part of removing second parasite, I think.
This is partial revert to commit 8c3b3bc2efa0 ("parasite-syscall:
deserialize compat parasite's answers").
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Parasite transfers pages in the same iovec format now: drop compatible
format (yay!).
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Let's try having one with two entries/exits.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
No need in two libraries if we have only one parasite blob.
With left hand I write code - with right I erase it.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As we have only one pie lib - no need to name it {native,compat}.
The next patch cleans Makefile.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's needed for ELF magic, not for platform.
Will help to simplify Makefile.library (the very next patch).
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To drop the second parasite blob, create another entry in 64-bit
parasite.
Didn't remove parasite-head-compat.S - it we gonna support native 32-bit
buids, we gonna need it.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I'll need them in parasite head and in exit.
travis-ci: success for Rectify 32-bit compatible C/R on x86
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now, when many useless options were dropped, it's easy to
provide a complete description of CLI in usage().
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After seeing a bunch of silent build failures, like this:
> GEN criu/pie/parasite-native-blob.h
> criu/pie/Makefile:121: recipe for target 'criu/pie/parasite-native-blob.h' failed
I finally took a look at why are they silent, only to discover that
compel prints errors to stdout, and of course its stdout is silenced
in criu/pie/Makefile (unless you run make with V=1, in which case
it prints tons and tons of very useful information). I am so shocked
by this evil plan!
Anyway, let's print errors to stderr like all sane programs do.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I am not quite sure how that happened, but compel hgen was not used for
ARM/ARM64, instead there's a simple version of it, called
gen-offsets.sh. The main difference is, shell script doesn't handle ELF
relocations, which apparently is not (currently?) needed for ARM.
It's bad to maintain two tools for the same functionality, so this
patch kills gen-offsets.sh and related stuff, making compel hgen
working on ARM. ELF relocations are still not handled, this code
is #ifdef-ed out for now and can be fixed to work on ARM later.
This patch also kills some macros and defines that seem obsoleted
now. For example, compel_relocs_apply() is now called unconditionally,
as it handles the trivial case of 0 relocs just fine.
Now, I checked that the blob headers generated by compel hgen and
gen-offsets.h are similar (i.e. generated blob code and values defined
are the same), but haven't done much above that.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This -u option always looked wrong to me, I mean, how the hell a user
is supposed to know where the hell those headers are? It took quite
a while to figure out what to do with it, but the end result is --
this option is not needed at all and can easily be dropped.
For finding paths to includes, there is a -I compiler option,
there's no need to specify something to compel.
In fact, it should know by itself where its own headers are kept
(and emit -I... to cflags if needed), but that's another story
which is to be told when we'll decide to pack compel as a standalone
tool. For now, just add "#include <compel/compel.h>" and be done.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The way the Makefile is written, parasite.h is added
to gcc command line, like this:
gcc -o spy spy.c libcompel.a parasite.h
Surely this is not what we want, as parasite.h is included to spy.c
The fix is to use "order-only prerequisite", as described by
https://www.gnu.org/software/make/manual/html_node/Prerequisite-Types.html
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is just to avoid a level of code block nesting/indentation
that can easily be avoided.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
They are no longer needed.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently, some compel internals are exposed to user API
(both C and CLI), making its usage more complicated than
it can be.
In particular, compel user have to specify a number of parameters
(names for various data) on the command line, and when in C code
assign a struc piegen_opt_t fields using the same names, without
using those identifiers anywhere else in the code.
It makes sense to hide this complexity from a user, which is what
this commit does.
First, remove the ability to specify individual names for data,
instead introducing a prefix that is prepended to all the names.
Second, generate a function %PREFIX%_setup_c_header() which does
all the needed assignments.
Third, convert users (criu/pie and compel test) to the new API.
NOTE that this patch breaks ARM, as compel hgen is not used for ARM.
This is to be fixed by a later patch in the series.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is purely cosmetical, no functional change.
1. Make sure relocs table is well aligned.
2. printf("%#02x", 1) prints 0x01, but for 0 it prints 0,
not 0x00 as one would expect, so output is somewhat ugly.
Use "0x%02x" format instead to make it more uniform and
well aligned.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Instead of hardcoding list of architectures to usage(), let's
generate it from the data.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
getopt_long() prints an error message and returns '?' in cases
- an unknown option is given
- a required option argument is missing
In such cases, we need to show usage and exit with an error.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case our command line is not good, it's not enough to just show
usage info -- it is much better to explicitly say what's wrong.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Without this check, if -o is not given, compel will fail with
the following error:
Can't open (null)
It's non-trivial to figure out that it means -o is required.
While at it, initialize the corresponding field.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It will be easier to modify that way.
This also fixes incorrect exit code from compel -h.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Checks for a number of arguments are to be done after option parsing.
With this patch, compel -V now works.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Got this when using compel hgen on arm 32-bit:
Error (compel/src/lib/handle-elf-host.c:115): String section header
@0xf66e11ec is out of [0xf66e1174, 0xf66e1264)
Looking at this, it does not make sense. For the reference,
sizeof(Elf_Shdr) is 0x28, so end position is also well within bounds.
Apparently, the check for string section header bounds is wrong
as the last argument of __ptr_struct_oob() is supposed to be a
region size, not the region end address as it is.
This always worked before because the check was too relaxed, and
compel was never used on 32-bit ARM. This time it didn't work
because of a 32-bit overflow, which helped to find this bug.
This is a fix to commit 6402f03 ("compel: separate get_strings_section
from __handle_elf").
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Simply run tracee from specfied IP assuming
it's arelady have trapping instruction in
stream.
It's unsafe low-level function use with caution.
travis-ci: success for compel: A fix and new helper
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Why should we have self-unmapping code in parasite?
It looks like, we can drop this code using simple sys_unmap()
injection (like that I did for `criu exec` action and for cases where we
failed to insert parasite by some reason, but still need to unmap remotes).
It's an RFC, so just a suggestion - maybe I miss something you have in
mind - please, describe that/those things.
My motivation is:
- less code, defined commands for PIE, one BUG() less, one jump to PIE less
- I'm making one 64-bit parasite on x86 instead of two 32 and 64 bit.
It works (branch 32-one-parasite) with long-jump in the beginning to
64-bit code from 32-bit task.
On parasite curing it sig-returns from 64-bit parasite to 32-bit task,
this point we're trapping in CRIU. After that we command parasite to
unmap itself, so it long-jumps again to parasite 64-bit code, unmaps,
we caught task after sys_unmap and the task is with 64-bit CS.
We can't set 32-bit registers after this - kernel checks that
registers set is the same on PTRACE_SETREGSET:
> > static int ptrace_regset(struct task_struct *task, int req, unsigned int type,
> > struct iovec *kiov)
...
> > if (!regset || (kiov->iov_len % regset->size) != 0)
> > return -EINVAL;
So, to return again to 32-bit task I need sigreturn() again or add
long-jump with 32-bit CS.
I've disable that for 32-bit testing with (in compel_cure_remote):
- if (ctl->addr_cmd) {
+ if (ctl->addr_cmd && user_regs_native(&ctl->orig.regs)) {
And it works. It also works for native tasks, so why should we keep it?
travis-ci: success for compel: kill self-unmap in parasite
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Cc: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The library can be used not only to run infection blobs,
but also just to execute syscalls remotely and here's
an example of how to do this.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
And, at the same time, an example of how to work with compel.
Based on titanic preliminary work of Cyrill :)
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It uses regs caller doesn't always know and is actually a
core routine under the API compel_syscall() one.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The size value should be page_size() aligned, which is
inconvenient for callers, and also differs from the bsize
only a little bit, so it's nicer to have the nr_gotpcrel
value which is anyway generated by compel hgen.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
These names are generated by compel hgen, so there's no
need in making callers know them.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The routine itself is in library, just forgot to putt the
declaration into UAPI header.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We use fds helpers in std plugin anyway
so just merge it in.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To ship plugins, libs and dev headers.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Because we build compel from toplevel directory
inclusion of "common/" doesn't cause any problem
but will in future (especially when our headers
start using it).
Thus add symlink immediately and it will be a notice
for installer that common directory in needed in uapi.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Right now we load blob into libcompel by providing values
from .h file which was generated by "compel hgen" command.
In the future we'd like to provide other ways (e.g. by
pusing mmap()-ed memory with .o file, or by .o file path),
so prepare for such future.
travis-ci: success for compel: Prepare for several ways to load blob into libcompel
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Where hgen stands for "header generator".
travis-ci: success for compel: Rename 'piegen' action into 'hgen'
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- extend handle_sigchld
- fix garbage return in compel_prepare
- handle errors in make_sock_for
travis-ci: success for compel: A few fixes and example
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's libcompel's helper. We need to address this problem later.
travis-ci: success for compel: A few fixes and example
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Implementation for PIE's builtin_memcpy located at
criu/arch/x86/include/asm/string.h
travis-ci: success for Compel/compat cleanups
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't need them in libcompel for PIE - only needed for C/R.
Fixes (with compat enabled back):
CC criu/arch/x86/sigaction_compat.o
In file included from criu/arch/x86/sigaction_compat.c:1:0:
/home/japdoll/tools/criu/criu/arch/x86/include/asm/restorer.h:15:25: error: unknown type name ‘tls_t’
extern void restore_tls(tls_t *ptls);
^~~~~
travis-ci: success for Compel/compat cleanups
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Libcompel is now responsible for system calls - criu already depends
on building of compel, this code is commented-out... Drop it!
travis-ci: success for Compel/compat cleanups
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Remove compatible sigset structure: as it has the same size for both
32-bit and 64-bit, I didn't use it across the code, only for a size check.
The check is removed as we use now only k_rtsigset_t.
Wordsize for sigset is changed to 64-bit - as it's written in comment
for possible 32-bit native building.
If we ever going to support compat mode for other archs, we will
need to re-introduce compat_sigset_t type if it has for those archs
different sizes for compat/native builds.
But for a while, let's simplify this.
travis-ci: success for Compel/compat cleanups
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now we have two routines one of which needs a callback for
proc parsing. This is complex, but needed by CRIU. For others
let's have a single "stop" call that would to everything.
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CRIU keeps all registers on CoreEntry and makes sigframe from
them as well, which means anyone using the compel library
have to provide own handlers, which is inconvenient. So
now it's possible to leave this task for libcompel itself:
it will save the regs and prerare sigframe on its own.
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CRIU sets up a child hander to get errors from tasks it
infects. For compel we'd have the same problem, so there's
a way to request for custom child handler, but compel
should provide some default by himself. And it's not clear
atm how this should look like, so here's a plain stub to
move forward.
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Compel needs a socket that lives in victim's net namespace.
CRIU creates this socket once for all the processes it works
with. For pure compel case the socket is created for each
new ctl.
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Yet again -- CRIU has an optimized openat()-based engine that
is slightly faster for opening "/proc" files rather than plain
open(). The latter is provided by default by compel.
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The ictx->syscall_ip is the address of any x-able VMA.
CRIU knows this as it parses the smaps file (heavily).
For others compel just parses /proc/pid/maps file.
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The original compel_prepare() also initializes the infect_ctx with
values suitable for simple usage. As a starting point the task_size
value is set.
The compel_prepare_noctx() allocates ctx-less handler that is to be
filled by the caller (CRIU).
travis-ci: success for compel: Contrinue improving library
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This one is needed only for task_size() on some arches and it is
simpler to keep this routine in compel .c rather than messing
with common/page.h installation.
https://travis-ci.org/xemul/criu/builds/177585567
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
PIE logger already in compel. Forgot to remove.
travis-ci: success for criu: Drop dangling symlink
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently we prepare a parasite socket only once and
save it in a static variable.
It's bad idea to use a static variable in a library.
In addition, it doesn't work if we have processes in
different network namespaces. In this case, we have to have
a separate socket for each namespace.
v2: fix compilation on Alpine
convert *p_sock into sock
travis-ci: success for compel: check whether a parasite socket is prepared each time (rev2)
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Providing infect functionality inside std plugin
doesn't look suite for me: the restorer has to define
dummy parasite_daemon_cmd/parasite_trap_cmd/parasite_cleanup
just to be able to compile with it.
So we have to define weak stubs right here in near future.
travis-ci: success for compel: The final infect move and install target
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
travis-ci: success for compel: The final infect move and install target
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- Add uapi header and start using it
- Add std_ prefix into functions and constants
- Drop unneeded headers
travis-ci: success for compel: The final infect move and install target
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The same as prev patch -- clean up the compel.h
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This only means introducing a compel_get_task_regs wrapper
over the get_task_regs() call that works on thread-ctl, not
thread-ctx.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The structure is opaque hander for thread infection.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The plan is to rectify the thread infection API and hide
thread_ctx from uapi eventually, so here's the symmetrical
to compel_task_sigmask() call for threads.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
piegen mode is cli only, so no need for them in library.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Currently criu built with criu/pie-util-fd (which
is a symlink to criu/pie/util-fd) with same flags
as we use in general compel infection code. Moreover
the criu link with libcompel.a, so we get a problem
where send_fds/recv_fds are multiple defined. Lets
rather unweave this mess:
- drop criu/pie-util-fd.c completely
- move send_fd/recv_fd inliners into scm.h
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
These were lost when moving code from CRIU, so pull them
back in.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This plugin is all about sending scm-s over unix sockets,
so having this stuff there is helpful.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now when *.lds is in compel we can switch to it. Also -- remove
the criu lds generation code.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In CRIU these are auto-generated, we want to have them in
compel and it looks like it's better to have them fixed
rather than generated.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This header was never actually required here.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The routine was #if0ed for a while (taken from older compel), now it's
time to provide any generic version.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
They will be needed for log module.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In UAPI there should be no -iquote-d headers.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise, messages printed by libcompel are omitted from logs.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Need in PTRACE_PEEKSIGINFO declarations:
criu/cr-dump.c: In function ‘dump_signal_queue’:
criu/cr-dump.c:901:16: error: ‘PTRACE_PEEKSIGINFO_SHARED’ undeclared (first use in this function)
arg.flags |= PTRACE_PEEKSIGINFO_SHARED;
^
criu/cr-dump.c:901:16: note: each undeclared identifier is reported only once for each function it appears in
criu/cr-dump.c:920:21: error: ‘PTRACE_PEEKSIGINFO’ undeclared (first use in this function)
nr = ret = ptrace(PTRACE_PEEKSIGINFO, tid, &arg, si);
^
Can be squashed with commit 638b0c2f11e1 ("compel: Move in parasite
engine").
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the final patch in the series. It does a bunch
of renames and fixes headers respectively.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We use it in both -- parasite engine and criu,
so export them as well.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The _desc is to describe where libcompel should task
parasite code from. For now the parasite is taken as
piece of memory, but more ways to load the code will
come soon.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Some pieces from infect-rpc are used by criu's pie code
which will soon be moved into compel std plugin itself,
so prepare for this.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the descriptor to be used by parasite code for
messages. In pure compel environment this will have to
be some file provided by caller or a pipe from which
libcompel will pull messages.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This moves the previously splitted routines into pie/infect.c.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The kdat is used to check whether we have compat sigreturn
in the kernel. Compel can check it himself, but criu already
knows this.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We will use syscall types in compel infect engine
itself so make sure they are built earlier.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We will need it when parasite engine will be creating signal frames.
Export appropriate headers and use it in CRIU by linking with libcompel.a.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
pr_out is only special left in piegen engine, the rest use
compel's pr_x output. Probably we will need to enhance it
one day to make same close to what we have in criu.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This includes
* The close_safe() routine for infect
* Callback for opening proc files on infect_ctx
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This removes restorer.h from infect. The header describes
routines, structures and constants messing with restorer blob.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is
* Move parasite_setup_regs() and related into arch/infect
* Move arch_can_dump_task() into infect
* Move parasite_send_fd() into infect-util
and completes parasite-syscall.h removal.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For now it's becoming the part of the compel API and lets
us remove parasite-syscall.h from infect.c. The former header
includes declarations of CRIU dumping routines that work with
parasite code.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The criu/ptrace.c will also go into compel sources, so
detach the needed code from CRIU as well.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This header describes CRIU parasite code, it has nothing
to do with infect, so remove it.
To do this we need to:
* Detach infect RPC commands from criu-parasite ones
* Move parasite_init_args and parasite_unmap_args into infect
* Move PARASITE_AREA_MIN into infect
* Hiding PARASITE_STACK_SIZE-s in infect
* Hiding parasite symbols resolvers in infect
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To be able to include compel/asm/ headers when needed.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Same split as was previously done with parasite-syscall.c now
with arch/*/crtools.c files.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I.e. -- the infect_ctX structure. Now it's in infect.h and
is aimed for compel sources.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
... and hide compel priv from parasite-syscall.
Now it's completely isolated inside compel.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Note -- presumably it's another functionality block inside compel,
so another .c file might be tempting here.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Note -- this will go away from compel API with cr-exec.c
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the code that lets caller place arguments into memory
shared between parasite and compel (or caller).
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Not only infect() routine but all dependant code too. This is
the core of the library actually.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This structure will be internal to compel. Users will only see
one as opaque pointer and read data from it using calls.
Exception for now -- infect_ictx. This is a configuration structure
that will be embeded into ctl and seen outside.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We'll collect the compel code here and will move all these
files into compel library by the last patch of this set.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now we can split the parasite_infect_seized() into CRIU-specific
part and independent part that is to become compel code.
The API to infect() is for now a bit clumsy, but I will rectify one
a bit more in the next patches.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is the address of an executable VMA. To get one
we need to parse /proc/pid/maps, compel will do it, but
since criu already parses this file (to dump task vmas),
we can provide the address via ictx.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Two calls -- to keep the registers and to put them back onto
sigframe. For CRIU the keeping is performed on CoreEntry.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
To track victim health state criu sets up the sigchild handler.
So will have to do the compel, but the ability to request for
own handler would be required.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
These will control various behavior of infection engine. For now
only fault-injections.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This structure will become the part of compel A[PB]I and
will be used by compel clients as configuration structure.
For now put there the pointer on a socket living in victim's
netns. If empty (-1), compel will create this socket its own,
but CRIU already creates such in an effective manner.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When seizeing task we need to parse /proc/pid/status for its
state, parent, signals and seccomp status.
In criu case we also parse other stuff in one go, so make
this parsing be a callback which criu will provide.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There's a subset of this structure is required by seize_catch_task(),
which in turn will go to compel library. So prepare for that.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The get_task_regs() call now accepts a pointer on a function that
is to keep obtained registers somwehere.
In CRIU case this "somewhere" is CoreEntry, for generic compel
user we'll need to add simple memcpy()-s to the library itself.
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
First time regs are saved on ctl->orig.regs in parasite_prep_ctl,
the 2nd time regs are got inside x86/arch_task_compatible, while
it can use the on-ctl copy.
travis-ci: success for Don't get task regs twice
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
travis-ci: success for Don't get task regs twice
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When compiled with clang-3.8 on ppc, compel complains:
> GEN criu/pie/parasite-native-blob.h
> parasite_native_blob: Error (compel/src/lib/handle-elf-host.c:541):
> Unsupported relocation of type 26
Look into R_PPC64_REL64/R_PPC64_ADDR64 and handle 32-bit the same way.
travis-ci: success for PPC+clang compile fixes
Cc: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Three reasons:
1. this flag doesn't work for ppc64 (see commit dc7b08b);
2. clang is not aware of this flag;
3. all seems to work just fine without it.
Cc: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In a manner similar to one of commit 9303ed3 ("Makefiles: move
-Wa,--noexecstack out of CFLAGS"), let's move this option to
linker flags (see the abovementioned commit for reasoning).
travis-ci: success for series starting with [1/3] compel: mv noexecstack from CFLAGS to LDFLAGS
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
While writing this, I somehow managed to miss the check of
how many entries were saved in core image.
So it may dereference here bs.
Fixes: #228
Fixes: commit 6fde3b8c27db ("x86: restore TLS")
travis-ci: success for x86, tls: read no more than saved TLS entries
Cc: Andrei Vagin <avagin@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Reported-by: Andrei Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The problem is, -Wa is a flag for assembler, but CFLAGS are also used
to generate dependencies, and clang complains loudly when it is used
for deps:
> > DEP compel/arch/x86/plugins/std/syscalls-64.d
> > clang-3.8: error: argument unused during compilation:
> > '-Wa,--noexecstack'
This patch moved the noexecflag from assembler to linker. I am not
100% sure but the end result seems to be the same.
This fixes dependency generation when using clang instead of gcc.
I surely have done my research before proposing this change, and
I have tested this change as good as I could.
Sorry, I should have provided more background in the commit message.
Here it goes.
There are a few ways to have non-executable stack:
1. mark the assembler source file (.S) with .section
.note.GNU-stack,"",%progbits
2. pass the -Wa,--noexecstack to compiler
3. pass the -z execstack to linker
All three ways are fine, let's see them in greater details.
Some people say (1) is the best way, but we have way too many
.S files now (23 of them, to be exact). Anyway, I can certainly do it
this way if you like, just let me know. It would look like this:
--- a/compel/arch/aarch64/plugins/std/syscalls/syscall-aux.S
+++ b/compel/arch/aarch64/plugins/std/syscalls/syscall-aux.S
@@ -3,6 +3,8 @@
* that are not implemented in the AArch64 Linux kernel
*/
+.section .note.GNU-stack,"",%progbits
+
ENTRY(sys_open)
mov x3, x2
mov x2, x1
Way (2) is what is currently used. Unfortunately it breaks dependency
generation with clang. One way to fix it would be to filter-out the bad
flag when we're generating deps. I tried experimenting with
$(filter-out) function in Makefiles today but it's complicated and I failed
to make it work.
Way (3) is what this commit offers. It seem to work fine while being
the least intrusive.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Got the following from clang:
> CC criu/parasite-syscall.o
> criu/parasite-syscall.c:1494:6: error: variable 'parasite_size' is used
> uninitialized whenever 'if' condition is false
> [-Werror,-Wsometimes-uninitialized]
> if (seized_native(ctl))
> ^~~~~~~~~~~~~~~~~~
> criu/parasite-syscall.c:1503:2: note: uninitialized use occurs here
> parasite_size += ctl->args_size;
> ^~~~~~~~~~~~~
> criu/parasite-syscall.c:1494:2: note: remove the 'if' if its condition
> is always true
> if (seized_native(ctl))
> ^~~~~~~~~~~~~~~~~~~~~~~
I look at the code and I'm still not quite sure whether parasite_size
can end up being uninitialized. Looks like for CONFIG_X86_64 it can.
So, let's initialize it.
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This patch fix a build break on ppc64le introduced by changes in the
compel's build option.
I factorized the common CFLAGS to make easier identifying particular
flags required by some architectures.
Fixes: fef01d79f7ee ("compel: cli -- Add more flags into cflags report")
travis-ci: success for compel: fix build break on ppc64le
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
When compel build objects it provides ".compel.init" and
".compel.exit" setions for plugins init/exit routines
and when we link PIE code in criu we simply zap them
out but code still reference to them inside std
text (even if we don't call them) so dont drop them.
Eventually compel will be loading plugins by self but
for now it's good for testing purpose to refernce
the plugin inside criu code.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is an addition to commit ed5b351.
travis-ci: success for Add compel-host to .gitignore
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Kir Kolyshkin <kir@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
They are not supported in plugins.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Not supported for a while.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
@std plugin known to fail when trying to execute,
investigating now. Meanwhile to not block tests
lets use syscalls object file.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
And use it in CRIU directly instead:
- move syscalls into compel/arch/ARCH/plugins/std/syscalls
- drop old symlinks
- no build for 32bit on x86 as expected
- use std.built-in.o inside criu directly (compel_main stub)
- drop syscalls on x86 criu directory, I copied them already
in first compel commist, so we can't move them now, but
delete in place
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Real syscalls generation is inside criu for a while
but will be moved out in the next patch.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CRIU will reference to them, but for now they are just stubs.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Both std and criu will use it for syscalls sake.
Note I've to disable x86 compat mode for a while:
we have to provide native types there thus will
back once everything else is complete.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
- linkage.h points to CRIU's asm specific
- prologue.h is just a link to x86, we will need to
fix it when start using std with other plugins
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Plain "main" makes compilers unhappy since it's
known predefined name.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As it's a make/build option, the set of files to compile depends
on it. We don't do feature tests on mrproper/clean (no point in it).
Let's define CONFIG_COMPAT for those targets, so compiled files
will be properly cleaned.
Reported-by: Adrian Reber <adrian@lisas.de>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As -lsoccr now is in $(LIBS) in Makefile.packages, it should be
build before criu objects. Otherwise, we try to compile
feature-tests with $(LIBS) and the succesful features fails with:
<stdin>:1:25: warning: extra tokens at end of #include directive
/usr/bin/ld: cannot find -lsoccr
collect2: error: ld returned 1 exit status
Which lead to later problems:
criu/sk-tcp.c:50:8: error: redefinition of 'struct tcp_repair_opt'
struct tcp_repair_opt {
^
In file included from criu/sk-tcp.c:1:0:
/usr/include/netinet/tcp.h:259:8: note: originally defined here
struct tcp_repair_opt
Because of fails in really-sucessful feture-tests.
P.S.
Maybe we should unbound feature-tests compilation from $(LIBS),
specified in Makefile.packages - that looks right after all.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
compel-host is needed to build criu itself and
run during piegen blob generation.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The default compel binary is the one compiled for target architecture.
The compel-host one is compel compiled for current arch that is needed
to build something for target arch.
We could use default compel if target arch == current arch, but this
makes things more complex.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Use new compel.h header with appropriate types.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This is fd passing via unix sockets (scm creds) suitable for use
by parasite code.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
prologue.h defines sys_recv() macro - let's use it by now
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The shmem pluging allows creation of shared memory segment between
parasite code and the caller.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The prologue includes routines needed for parasite blob to work
and is always included with the std plugin.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Fixes:
GEN compel/include/version.h
GEN compel/include/version.h
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Delete plugins/include/asm/std directory - let it be without plugin name.
Make symlinks to reuse criu's files, except those, which will
be deleted after libcompel from criu (like syscalls).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The plugin provides basic features as string copying, syscalls, printing.
Not used on its own by now but will be shipping by default with other
plugins.
With great help from Dmitry Safonov.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Will be used later.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As we meet this before, I think, we should abort generation here.
No point for making PIE with external symbols for us (at least, yet),
so let's break build than find the problem at runtime.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's used in restorer to map compatible vDSO blob.
When !CONFIG_COMPAT it's not needed and even more:
vdso_fill_symtable_compat is macro and is undefined in that
case. It will never shoot, as compat_vdso is always false
for that case, but get rid of it.
I also need to leave CONFIG_X86_64 here, as arch_prctl()
is not defined for x86_32.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The other way to solve this is to compile shared between
CRIU and PIEs objects twice: without stack-protection and
with environment choice. But I don't think it worth it.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I think, we could transpher also `-m elf_i386' and `-m32' to
compel output - but only in case if we will not support
native x86_32 in compel (as they are wrong for native build).
Or introduce something like compat_ia32 in compel option, not sure.
Left in makefile for a while.
Also it would be good to remove $(LD_R) in makefile and use
compel output for ldflags, but that will be valid only when compel
will support arm arch.
Fixes (with the following patches):
GEN criu/pie/parasite-compat-blob.h
parasite_compat_blob: Error (compel/handle-elf-32.c:322): Unexpected undefined symbol: `__stack_chk_fail'. External symbol in PIE?
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
As we will not support *native* 32-bit i386 build, I dropped some
ifdefs, introducing instead of ifdef(CONFIG_X86_64) --
ifdef(CONFIG_COMPAT).
CRIU should build now without ia32 Glibc and gcc-multilib support.
Maybe I should add some warning that the build is made without
compatible task support (or criu check should print that),
will do as compat patches hit master.
Fixes: #181
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I'll wrap all compatible code in this CONFIG_COMPAT define.
As I'll wrap also compatible parasite generation in this,
it's also makefile variable, rather than just C define.
The test itself consists of including stubs-32.h, which is
glibc6-i686 presence test and is compiled with -m32 option,
which is test for gcc-multilib.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Cc: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In is_required_syscall() req_sysnr is set according to the native mode
so we can check the syscall number directly against it.
No functional change expected.
Cc: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Laurent Dufour <ldufour@linux.vnet.ibm.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Target criu depends on all, so this is redundant and makes noise:
if you had typed `make` without arguments, it has built compel firstly,
if you had typed `make criu`, it has built protobuf images firstly.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
@gpregs_case is a bit vague name, lets
define traditional @mode here.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Tried hard to save compile-time static type checking and make code
more readable, hiding native/compat details in macros.
I think, it's better now.
Also BTW fixes: #188 (and compatible zdtm test)
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
So, I made a mistake in find_syscall: it can't use arch_task_compatible
to find out in which mode the application is (native/compat).
The reason is that arch_task_compatible uses PTRACE_GETREGSET.
And at the moment of find_syscall we haven't yet seized the task.
In this patch I move syscall's number check right before injecting
a syscall, where we have parasite_ctl with all needed information
about task's mode.
This makes error-path for wrong syscall number longer and subtler
(includes curing now), but I think it's a corner-case, so as
it makes error-less path to execute_syscall shorter and without
additional ptrace syscalls, it's better.
Reported-by: Andrew Vagin <avagin@virtuozzo.com>
Cc: Andrew Vagin <avagin@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
ptrace_get_regs correctly returns error code in case of failure,
but for debugging reasons let's add error printing in case of
PTRACE_GETREGSET failed right after the call to ptrace().
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
CID 163751 (#1 of 1): Big parameter passed by value (PASS_BY_VALUE)
pass_by_value: Passing parameter regs of type user_regs_struct_t (size 224 bytes) by value.
Signed-off-by: Andrew Vagin <avagin@virtuozzo.com>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
- use entry/end from linkage
- use macros for segments
- use C style comments
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Tested-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Otherwise compiler nicely align it for us on 24 bytes.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The kernel patch "x86/signal: add SA_{X32,IA32}_ABI sa_flags" makes
signal's ABI the same as sigaction's syscall ABI instead of per-thread's
TIF_IA32 flag.
So for delivering signals with compatible ABI, we need to call
sigaction through raw int80 exception.
This patch restores signals with int80: cr-restore part and PIE restorer's
part lay in sigaction_compat.c, which compiled for criu binary and for
restorer PIE.
The PIE's part is needed strictly for setting SIGCHLD handler, other
signal handlers are set in cr-restore (as it was before).
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
`make test COMPAT_TEST=y` will build all executable tests as i386 ELFs.
For building tests, need the following libraries from multilib:
libaio.i686 libaio-devel.i686 libcap-devel.i686 libcap.i686
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Put dumped TLS descriptors back to GDT.
Do it only if it was present.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Dump TLS with the help of SYS_get_thread_area.
Primary for 32-bit applications, but this also may be used by
mixed 64/32 bit code. I do not enable dumping for 64 bit unless
we'll meet such code, but include 3 user_desc entries of TLS
as not present in 64-bit images.
That's arguable and I may include user_descs only for compat tasks.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I prefer this to be done in callee, than in caller for simplicity.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I need it to call sigaction from 32-bit code as kernel will
set sigframe ABI according to sigaction call ABI.
Also I will call {get,set}_thread_area to restore TLS entries.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
While restorering compatible application on x86-64, we need
to parse 32-bit vDSO. By that reason I need _three_ compiled
object versions for util-vdso:
- for native parasite it's util-vdso.o
- for compatible parasite it's compat/util-vdso.o
- for restorer it's util-vdso.o and util-vdso-elf32.o
Note, that I can't link compat/util-vdso.o to restorer, as it's
i386 ELF which ld can't link to x86_64 ELF file.
TODO: maybe I'll need to refactor and introduce generic
CONFIG_COMPAT instead of those defined(CONFIG_X86_32).
Fixes:
pie: 27504: vdso: Mapping compatible vDSO at 0x25000
pie: 27504: Remap 0x7f3de3efa000->0x8048000 len 0x1000
...
pie: 27504: vdso: Parsing at 0xf7776000 0xf7778000
pie: 27504: Error (pie/util-vdso.c:87): vdso: Elf header magic mismatch
pie: 27504: Error (pie/restorer.c:1540): Restorer fail 27504
(00.029188) Error (cr-restore.c:988): 27504 exited, status=1
(00.033072) Error (cr-restore.c:1870): Restoring FAILED.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Map here instead of park before unmap.
TODO: need to check that mapped size is smaller than x86_64 vDSO.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We need to do it in pure ia32 asm.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Change page_xfer_dump_pages the way it could handle compatible iovs.
Separated hole dumping in page_xfer_dump_hole and introduced
iterator function get_iov which will return native iovec,
converting compatible iovec if needed.
Fixes:
(00.009060) Fetched ack: 7 7 0
(00.009061) Transfering pages:
(00.009062) buf 16/16
(00.009063) p 0x100008048000 [32841]
(00.009101) Error (page-xfer.c:504): Only 65536 of 17592320561152 bytes have been spliced
(00.009253) page-pipe: Killing page pipe
(00.009263) ----------------------------------------
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Compatible parasite will use standard types, which are sized
as _args_compat structures in "parasite-compat.h".
Sometimes I miss high-level overloading in C.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Generic code uses raw syscall numbers for:
- syscall_seized, to execute through parasite control needed syscall;
- parasite_stop_on_syscall, to trap couple of tasks on needed syscall.
As syscall numbers may differ (and differ for x86) between native and
compatible mode, we need proper syscall wrapper here.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Seems like, offset was broken. And it had typo: leal -> movl
(according to 64-bit parasite header), as cmd parameter is int
(not pointer to int) in parasite_service:
int __used __parasite_entry parasite_service(unsigned int cmd, void *args)
Fixed - loads good now.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Do pure 32-bit sigreturn.
Change code selector, do 0x80 rt_sigreturn.
We should have here remapped 32-bit vDSO, all should be fine.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I tried to split this patch as much as it goes, but still
it's quite huge.
Mostly it has many compatible structures declarations.
Lesser it contains adaptation to new native/compat sigframe duality.
The only logic that changed by this patch is the order of
creating sigframe in construct_sigframe.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Impact: just a bit more info for debugging.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It took a little time on travis (I didn't measure, just starred
at build and it added not visible delay for build).
But it will help to verify that compel works on all supported arches.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now it looks prettier. Also deleted unnecessary parameters from
test's functions.
No functional changes.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now it has 4 new tests:
ok 4 - section table start oob (64-bit ELF)
ok 5 - too many sections in table (64-bit ELF)
ok 6 - strings section's header oob of section table (64-bit ELF)
ok 7 - strings section oob (64-bit ELF)
I.e, if we forget to test string section's header oob with the next diff:
>--- a/compel/handle-elf.c
>+++ b/compel/handle-elf.c
>@@ -122,7 +122,7 @@ static const char *get_strings_section(Ehdr_t *hdr, uintptr_t mem,
> pr_err("String section @%#zx size %#lx is out of [%#zx, %#zx)\n",
> addr, (unsigned long)secstrings_hdr->sh_size,
> mem, mem + size);
>- return NULL;
>+ return (void*)addr;
> }
>
> return (void*)addr;
It will yell with:
ok 1 - zero ELF header (64-bit ELF)
...
not ok 6 - strings section's header oob of section table (64-bit ELF), expected -4 but ret is -1
...
not ok 12 - strings section's header oob of section table (32-bit ELF), expected -4 but ret is -1
Should be more useful when I add relocations tests after all.
(but this seems for me useful too).
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@gmail.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Sorry for introducing that, but we need to force-rebuild implicit
rules on the level of main Makefile. All the sub-makefiles should
decide if the force-rebuilding target really needs a rebuild,
because they know it's dependencies.
Pattern-specific rules are implicit, so something like:
.PHONY: compel/% criu/% #...
will not work.
.FORCE target seems the simplest way to solve this
"going to submake on rebuild" problem.
But maybe there is more elegant proposal?
FWIW, before this patch:
[criu]$ make compel/compel
make[1]: Entering directory '~/tools/criu'
HOSTDEP compel/handle-elf-32.d
...
HOSTLINK compel/compel
make[1]: Leaving directory '~/tools/criu'
[criu]$ touch compel/main.c
[criu]$ make compel/compel
make: 'compel/compel' is up to date.
[criu]$ touch compel/Makefile
[criu]$ make compel/compel
make: 'compel/compel' is up to date.
After the patch:
[criu]$ touch compel/main.c
[criu]$ make compel/compel
make[1]: Entering directory '~/tools/criu'
HOSTDEP compel/main.d
HOSTCC compel/main.o
HOSTLINK compel/compel
make[1]: Leaving directory '~/tools/criu'
[criu]$ touch compel/Makefile
[criu]$ make compel/compel
make[1]: Entering directory '~/tools/criu'
HOSTDEP compel/handle-elf-32.d
...
HOSTLINK compel/compel
make[1]: Leaving directory '~/tools/criu'
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Well, I hope, I will not make integer promotion mistakes anymore:
> 6.3.1.1
> If an int can represent all values of the original type, the value
> is converted to an int; otherwise, it is converted to an unsigned int.
> These are called the integer promotions.48) All other types are
> unchanged by the integer promotions.
>>> CID 161317: (SIGN_EXTENSION)
>>> Suspicious implicit sign extension: "hdr->e_shentsize" with type
"unsigned short" (16 bits, unsigned) is promoted in
"hdr->e_shentsize * hdr->e_shnum" to type "int" (32 bits, signed),
then sign-extended to type "unsigned long" (64 bits, unsigned).
If "hdr->e_shentsize * hdr->e_shnum" is greater than 0x7FFFFFFF,
the upper bits of the result will all be 1.
96 size_t sec_table_size = hdr->e_shentsize * hdr->e_shnum;
>>> CID 161317: (SIGN_EXTENSION)
>>> Suspicious implicit sign extension: "hdr->e_shentsize" with type
"unsigned short" (16 bits, unsigned) is promoted in
"hdr->e_shentsize * hdr->e_shstrndx" to type "int" (32 bits, signed),
then sign-extended to type "unsigned long" (64 bits, unsigned).
If "hdr->e_shentsize * hdr->e_shstrndx" is greater than 0x7FFFFFFF,
the upper bits of the result will all be 1.
111 addr = sec_table + hdr->e_shentsize * hdr->e_shstrndx;
Fixes: #157
Fixes: commit 36664a3cabec ("compel: separate get_strings_section from
__handle_elf").
Reported-by: Coverity
Reported-by: Andrew Vagin <avagin@virtuozzo.com>
Cc: Andrew Vagin <avagin@virtuozzo.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Yet they only test for ELF header, but soon I'll add more of them.
It's build with
$ make test/compel/handle_binary
and test output is in TAP format:
$ ./test/compel/handle_binary
ok 1 - check zero ELF header
ok 2 - check non-supported ELF header
ok 3 - check non-relocatable ELF header
ok 4 - check zero ELF header
ok 5 - check non-supported ELF header
ok 6 - check non-relocatable ELF header
(here two runs for x86_64 and x86_32 ELF binaries)
I'm planning to integrate it with Travis, so we will be
sure that compel is properly working (as this tests doesn't need
any ns and may be run on qemu-static).
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
For tests, we need to know if elf file parsing was interrupted
in a proper place (and thus meaningful error numbers).
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
That will help to omit pr_* output on the screen on tests,
where one can redefine `opts`.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I copied __ptr_oob* checks from util-vdso.c.
That will allow to check not only structure begin pointers,
but structure end also.
Before this patch code checked if strings section's header pointer is OOB,
but it did it after dereferencing this pointer, which is meaningless.
Now it checks:
- OOB of sections table,
- strings section's header should be inside sections table,
- check strings section with it's length for OOB.
In the very next patches I will add tests for this functions and
other compel-related changes.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
There is no longer phony compel target but compel/compel instead.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I think, it's more pretty to pass -DCONFIG_X86_* instead of all
$DEFINES. That simplifies the statement and makes it more readable.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Sorry for this typo, I should be more attentive.
Fixes: commit ea523b183326 ("compel: shuffle skeleton a bit").
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Split handle_elf() function from main.c to per-arch.
Rename it to handle_binary not to cross-reference.
Rename generic handle_elf to __handle_elf as with define
not to litter namespace.
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
I propose to change compel directory structure:
- if we want support more arch's than x86/ppc66, it seems
worth to add arch/ folder
- move all sources from src/ folder up
- to have headers and build additional object with CFLAGS for
a symlink seems for me less hacky way than mess around
with .c files cross-linking
- I made handle-elf.h header for arch helpers code. I may named
that just "elf.h", but that may confuse, as there are <elf.h>
system header
- I would like to drop those ELF_PPC64/ELF_X86_32/ELF_X86_64
defines and use CONFIG_X86_64 and whatnot
After this patch compel directory become:
compel/
├── arch
│ ├── ppc64
│ │ └── include
│ │ └── handle-elf.h
│ └── x86
│ └── include
│ └── handle-elf.h
├── handle-elf-32.c -> handle-elf.c
├── handle-elf.c
├── include
│ ├── piegen.h
│ └── uapi
│ ├── elf32-types.h
│ ├── elf64-types.h
│ └── types.h
├── main.c
└── Makefile
Note: temporary I make value32 and addend32 for compilation on arm/aarch64
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
With `-r` option relocation to parasite_service
was not made on ARM:
0x76dbc018: bl 0x76dbc018 0xebfffffe
(You may saw it with objdump also).
This leaded to hang at "Putting tsock" message:
(01.368297) ----------------------------------------
(01.368321)
(01.368339) Collecting fds (pid: 13503)
(01.368360) ----------------------------------------
(01.368535) Found 3 file descriptors
(01.368564) ----------------------------------------
(01.368648) Dump private signals of 13503
(01.368708) Dump shared signals of 13503
(01.368761) Parasite syscall_ip at 0x10000
(01.369605) Set up parasite blob using memfd
(01.369641) Putting parasite blob into 0x76cc5000->0x76e1f000
(01.369755) Dumping GP/FPU registers for 13503
(01.369818) Putting tsock into pid 13503
Link against native.lib.a which also fixes build for aarm64.
Reported-by: alex vk <avankemp@gmail.com>
Reported-by: long.wanglong <long.wanglong@huawei.com>
Cc: Cyrill Gorcunov <gorcunov@gmail.com>
Cc: Christopher Covington <cov@codeaurora.org>
Reviewed-by: Christopher Covington <cov@codeaurora.org>
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Reviewed-by: Christopher Covington <cov@codeaurora.org>
Reviewed-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In case of error don't re-close files already closed.
https://github.com/xemul/criu/issues/148
Reported-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Reviewed-by: Andrey Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's included through "asm/restorer.h".
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This will document that {get,set}_user_reg should be used
only on initialized register set. Otherwise, after some code
changes we may find ourself in situation when setting not
inited user regs will set them for compatible register set:
(is_native == false).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Detect task's personality by the size of register set, returned
by ptrace call with PTRACE_GETREGSET (more reliable).
The same approach uses strace from 4.8 version:
https://sourceforge.net/projects/strace/files/strace/4.8/
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Introduced user_regs_struct32.
Other changes mainly are reforming existing code to use the new
register sets union.
For protobuf images - reuse user_x86_regs_entry for both compatible
and native tasks with enum in the beggining that describes register
set type. That's better and simpler, than introducing a new 32-bit
register set for compatible tasks. I tried to do this firstly with
oneof keyword:
499c93ae0e
But protobuf supports oneof keyword only from recent version 2.6.0,
so I tried to rework it into enum + 2 register sets:
aab4489bd4
But that did not work either because restorer pie takes gpregs as
thread_restore_args parameter and UserRegsEntry shouldn't contain
pointers, but structure objects. This may be fixed by redefining
UserRegsEntry not as typedef for UserX86RegsEntry, but containing
needed objects, than treat it right for restorer - but that's
more complicated that reusing user_x86_regs_entry.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Only parasite should be mode-depended, not restorer, as
restorer will just switch to compatible mode with arch_prctl
at the end and jump to 32-bit executable with sigreturn.
So for parasite there are two targets: "native" and "compat",
and one for restorer with the same name "restorer".
It will result in parasite-native.o, parasite-compat.o and restorer.o
objects.
Pie build still may work with piegen or without it (gen-offset.sh).
There are many FIXME in this patch, all them are in C code, that should
be fixed to use compatible parsite when needed.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
In code they yet use native parasite type, but in definition
this parameter is not used (will be used at the next patch).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Now compatible objects will be in $(obj)/compat/$(basename)-compat.o
I can't use just $(obj)/compat/$(basename).o as basename for file
will be the same as for native object, which wouldn't work by
the reason of CFLAGS_$(F) in nmk-ccflags.
So, I need different names for compatible/native objects.
Because I don't want to make a mess in parent directories,
I put this symlinks to compat/ dirs.
This is how I came to that decision (even if I do not like it).
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
First pie library to use for compiling native pie.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Impact: search sys-exec-tbl-32.c for compatible tasks.
Rename task_in_compat_mode to arch_task_compatible and use it in
find_syscall for 64-bit to check compatible task's syscall nr.
It still will not execute syscall in 32-tasks, as we still do not
have 32-bit pie (arch_can_dump_task will return false for these tasks).
NOTE: be sure to `make mrproper` on criu directory before applying this
patch, as before `criu/arch/x86/sys-exec-tbl.c` was autogenerated,
it will make conflict if you try to apply this patch on dirty directory.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
After uncommenting FIXME:
It will add sc_exec_table_32 for compatible tasks to sys-exec-tbl.c
Now it does:
- add two different 32/64 syscall tables for cr-exec
sys-exec-tbl-{64,32}.
- add two different syscall headers syscall-{64,32}.h,
that are included from more x86 generic syscall.h depending
on -DCONFIG_X86_{32,64} option.
- builds two different syscalls-{32,64}.built-in.o
- for criu core files, that need SYS_memfd_create and other
SYS_* __NR_* defines (currently kerndat.c and shmem.c),
create simple syscall-codes.h that includes syscall-codes-64.h
[Added after rebase on master]
That way after apply, the compatible patch set will be simply
able to bisect for regressions.
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
It's a hostprog so one target is enough,
otherwise we're gitting double deps generation.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
We don't need it actually.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Acked-by: Andrew Vagin <avagin@virtuozzo.com>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
The compel component is a replacement for several aspects of CRIU
functionality: binary blobs generation for PIE parasite/restore code,
and a library for parasite code injection and execution (to be implemented).
In the commit we rather shuffle compel into own directory and
use it for
1) Fetching cflags when compiling PIE blobs
2) Use its "piegen" functionality to generate blobs themselves.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Here we introduce actions:
- "piegen" to generate blobs, which is used
by criu already;
- "cflags" and "ldflags" to print out options
needed for compiler and linker when building
compel compatible objects.
We rather moved old "main" function body into
piegen helper function and implement the rest
of actions since they are one-liners.
Note the usage uses new "compel" brand, but it's
safe because we don't export anything yet.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
This will be needed to print out cflags and ldflags.
Unused at moment.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Fixes the following error on travis-ci:
CC arch/x86/syscalls/syscall32.o
In file included from /usr/include/signal.h:28:0,
from /home/travis/build/0x7f454c46/criu/criu/arch/x86/include/asm/types.h:5,
from arch/x86/syscalls/syscall32.c:1:
/usr/include/features.h:374:25: fatal error: sys/cdefs.h: No such file or directory
# include <sys/cdefs.h>
^
Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com>
Acked-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Pavel Emelyanov <xemul@virtuozzo.com>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
2017-03-14 21:03:20 +03:00
2048 changed files with 158278 additions and 33605 deletions
Before reporting a new issue, please make sure that it's not a duplicate.
If you suspect your issue is a bug, please provide information as shown below. If your issue is a feature request, this information is not always necessary.
-->
**Description**
<!--
Briefly describe the problem you are having in a few paragraphs.
-->
**Steps to reproduce the issue:**
1.
2.
3.
**Describe the results you received:**
**Describe the results you expected:**
**Additional information you deem important (e.g. issue happens only occasionally):**
**CRIU logs and information:**
<!--
You can either attach logs as files to the issue or put them under details
-->
<details><summary>CRIU full dump/restore logs:</summary>
<p>
```
(paste your output here)
```
</p>
</details>
<details><summary>Output of `criu --version`:</summary>
<p>
```
(paste your output here)
```
</p>
</details>
<details><summary>Output of `criu check --all`:</summary>
CRIU project is (almost) the never-ending story, because we have to always keep up with the
Linux kernel supporting checkpoint and restore for all the features it provides. Thus we're
looking for contributors of all kinds -- feedback, bug reports, testing, coding, writing, etc.
Here are some useful hints to get involved.
* We have both -- [very simple](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement) and [more sophisticated](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3A%22new+feature%22) coding tasks;
* CRIU does need [extensive testing](https://github.com/checkpoint-restore/criu/issues?q=is%3Aissue+is%3Aopen+label%3Atesting);
* Documentation is always hard, we have [some information](https://criu.org/Category:Empty_articles) that is to be extracted from people's heads into wiki pages as well as [some texts](https://criu.org/Category:Editor_help_needed) that all need to be converted into useful articles;
* Feedback is expected on the GitHub issues page and on the [mailing list](https://lore.kernel.org/criu);
* We accept GitHub pull requests and this is the preferred way to contribute to CRIU. If you prefer to send patches by email, you are welcome to send them to [CRIU development mailing list](https://lore.kernel.org/criu).
Below we describe in more detail recommend practices for CRIU development.
* Spread the word about CRIU in [social networks](http://criu.org/Contacts);
* If you're giving a talk about CRIU -- let us know, we'll mention it on the [wiki main page](https://criu.org/News/events);
### Setting up the development environment
Although `criu` could be run as non-root (see [Security](https://criu.org/Security)), development is better to be done as root. For example, some tests require root. So, it would be a good idea to set up some recent Linux distro on a virtual machine.
### Get the source code
The CRIU sources are tracked by Git. Official CRIU repo is at https://github.com/checkpoint-restore/criu.
The repository may contain multiple branches. Development happens in the **criu-dev** branch.
To clone CRIU repo and switch to the proper branch, run:
Follow these steps to compile CRIU from source code.
#### Installing build dependencies
First, you need to install the required build dependencies. We provide scripts to simplify this process for several Linux distributions in [contrib/dependencies](contrib/dependencies). For a complete list of dependencies, please refer to the [installation guide](https://criu.org/Installation).
##### On Ubuntu/Debian-based systems:
```
./contrib/dependencies/apt-packages.sh
```
##### On Fedora/CentOS-based systems:
```
./contrib/dependencies/dnf-packages.sh
```
##### Using Nix:
```
nix develop
```
#### Compiling CRIU
Once the dependencies are installed, you can compile CRIU by running the `make` command from the root of the source directory:
```
make
```
This should create the `./criu/criu` executable.
## Edit the source code
When you change the source code, please keep in mind the following code conventions:
* code is written to be read, so the code readability is the most important thing you need to have in mind when preparing patches
* we prefer tabs and indentations to be 8 characters width
* we prefer line length of 80 characters or less, more is allowed if it helps with code readability
* CRIU mostly follows [Linux kernel coding style](https://www.kernel.org/doc/Documentation/process/coding-style.rst), but we are less strict than the kernel community
Other conventions can be learned from the source code itself. In short, make sure your new code looks similar to what is already there.
## Automatic tools to fix coding-style
Important: These tools are there to advise you, but should not be considered as a "source of truth", as tools also make nasty mistakes from time to time which can completely break code readability.
The following command can be used to automatically run a code linter for Python files (ruff), Shell scripts (shellcheck),
text spelling (codespell), and a number of CRIU-specific checks (usage of print macros and EOL whitespace for C files).
```
make lint
```
In addition, we have adopted a [clang-format configuration file](https://www.kernel.org/doc/Documentation/process/clang-format.rst)
based on the kernel source tree. However, compliance with the clang-format autoformat rules is optional. If the automatic code formatting
results in decreased readability, we may choose to ignore these errors.
Run the following command to check if your changes are compliant with the clang-format rules:
```
make indent
```
This command is built upon the `git-clang-format` tool and supports two options `BASE` and `OPTS`. The `BASE` option allows you to
specify a range of commits to check for coding style issues. By default, it is set to `HEAD~1`, so that only the last commit is checked.
If you are developing on top of the criu-dev branch and want to check all your commits for compliance with the clang-format rules, you
can use `BASE=origin/criu-dev`. The `OPTS` option can be used to pass additional options to `git-clang-format`. For example, if you want
to check the last *N* commits for formatting errors, without applying the changes to the codebase you can use the following command.
```
make indent OPTS=--diff BASE=HEAD~N
```
Note that for pull requests, the "Run code linter" workflow runs these checks for all commits. If a clang-format error is detected
we need to review the suggested changes and decide if they should be fixed before merging.
Here are some bad examples of clang-format-ing:
* if clang-format tries to force 120 characters and breaks readability - it is wrong:
```
@@ -58,8 +59,7 @@ static int register_membarriers(void)
The `Assisted-by` tag should be placed after the commit message body
and before the `Signed-off-by` line.
Note that AI agents should not add `Signed-off-by` tags. Only human
developers can certify the Developer's Certificate of Origin. The
submitter is responsible for reviewing all AI-generated code and
ensuring its correctness and license compliance.
## Submit your work upstream
We accept GitHub pull requests and this is the preferred way to contribute to CRIU.
For that you should push your work to your fork of CRIU at [GitHub](https://github.com) and create a [pull request](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests)
### Pull request guidelines
Pull request comment should contain description of the problem your changes
solve and a brief outline of the changes included in the pull request.
Please avoid pushing fixup commits to an existent pull request. Each commit
should be self contained and there should not be fixup commits in a patch
series. Pull requests that contain one commit which breaks something
and another commit which fixes it, will be rejected.
Please merge the fixup commits into the commits that has introduced the
problem before creating a pull request.
It may happen that the reviewers were not completely happy with your
changes and requested changes to your patches. After you updated your
changes please close the old pull request and create a new one that
contains the following:
* Description of the problem your changes solve and a brief outline of the
changes
* Link to the previous version of the pull request
* Brief description of the changes between old and new versions of the pull
request. If there were more than one previous pull request, all the
revisions should be listed. For example:
```
v3: rebase on the current criu-dev
v2: add commit to foo() and update bar() coding style
```
If there are only minor updates to the commits in a pull request, it is
possible to force-push them into an existing pull request. This only applies
to small changes and should be used with care. If you update an existing
pull request, remember to add the description of the changes from the
previous version.
### Mailing list submission
Historically, CRIU worked with mailing lists and patches so if you still prefer this way continue reading till the end of this section.
### Make a patch
To create a patch, run
```
git format-patch --signoff origin/criu-dev
```
You might need to read GIT documentation on how to prepare patches
for mail submission. Take a look at http://book.git-scm.com/ and/or
http://git-scm.com/documentation for details. It should not be hard
at all.
We recommend to post patches using `git send-email`
If you get tired of typing `--to=criu@lists.linux.dev` all the time,
you can configure that to be automatically handled as well:
```
git config sendemail.to criu@lists.linux.dev
```
If a developer is sending another version of the patch (e.g. to address
review comments), they are advised to note differences to previous versions
after the `---` line in the patch so that it helps reviewers but
doesn't become part of git history. Moreover, such patch needs to be prefixed
correctly with `--subject-prefix=PATCHv2` appended to
`git send-email` (substitute `v2` with the correct
version if needed though).
### Mail patches
The patches should be sent to CRIU development mailing list, `criu AT lists.linux.dev`. Note that you need to be subscribed first in order to post. The list web interface is available at https://lore.kernel.org/criu; you can also use standard mailman aliases to work with it.
Please make sure the email client you're using doesn't screw your patch (line wrapping and so on).
> **Note:** When sending a patch set that consists of more than one patch, please, push your changes in your local repo and provide the URL of the branch in the cover-letter
### Wait for response
Be patient. Most CRIU developers are pretty busy people so if
there is no immediate response on your patch — don't be surprised,
sometimes a patch may fly around a week before it gets reviewed.
## Continuous integration
Wiki article: [Continuous integration](https://criu.org/Continuous_integration)
CRIU tests are run for each series sent to the mailing list. If you get a message from our patchwork that patches failed to pass the tests, you have to investigate what is wrong.
On x86_64, there are two types of compatibility mode applications:
- ia32: Compiled to run on an i686 target, these can be executed on x86_64 if the `IA32_EMULATION` configuration option is enabled.
- x32: Specially compiled binaries designed to run on x86_64 with the `CONFIG_X86_X32` configuration option enabled.
Both use 4-byte pointers and thus can address no more than 4 GB of virtual memory.
However, x32 uses the full 64-bit register set and therefore cannot be launched natively on an i686 host.
Both require an additional environment on x86_64, such as Glibc, libraries, and compiler support.
x32 is rarely distributed; currently, only the [Debian x32 port](https://wiki.debian.org/X32Port) is easily found.
Currently, CRIU supports ia32 C/R. Support for x32 can be added relatively easily, as the necessary kernel patches for ia32 C/R are already in place.
In this document, the terms *compatible* and *32-bit* refer to ia32 applications unless otherwise specified.
## Difference between native and compatibility mode applications
From the CPU's point of view, 32-bit compatibility mode applications differ from 64-bit applications by the current Code Segment (CS) selector. If the L-bit (Long mode) in the segment descriptor is set, the CPU operates in 64-bit mode when that descriptor is used. There are other differences between 32-bit and 64-bit selectors; for more details, see [the article "The 0x33 Segment Selector (Heavens Gate)"](https://www.malwaretech.com/2014/02/the-0x33-segment-selector-heavens-gate.html). Code selectors for both modes are defined in kernel headers as `__USER32_CS` and `__USER_CS`, corresponding to descriptors in the Global Descriptor Table (GDT). The mode can be switched from 64-bit to compatibility mode by changing the CS value (e.g., using a long jump).
From the Linux kernel's point of view, applications differ based on values set during `exec`, such as `mmap_base` or thread info flags like `TIF_ADDR32`, `TIF_IA32`, or `TIF_X32`.
Both native and compatibility mode applications can perform either 32-bit or 64-bit syscalls.
## Mixed-bitness applications
The current kernel ABI allows for the creation of mixed-bitness applications, which can become quite complex.
For instance, an application could set both 32-bit and 64-bit robust futex list pointers.
Alternatively, a multi-threaded application could have some threads executing 32-bit code while others execute 64-bit code.
If support for such mixed-bitness applications is ever needed, it could be added to CRIU relatively easily. However, this should likely be a compile-time configuration option to avoid adding unnecessary syscalls to standard C/R operations.
Currently, there are no plans to add this support, as such applications are unlikely to be encountered outside of synthetic tests.
## Approaches to C/R for compatibility mode applications
32-bit C/R can be implemented in several ways. This section describes the pros and cons of various approaches and explains why the current implementation was chosen.
### Restore via exec() of a 32-bit dummy binary vs. from 64-bit CRIU
Restoring a 32-bit application could be done using a 32-bit daemon that communicates with the 64-bit CRIU binary or a 32-bit CRIU subprocess.
**Pros**:
- No kernel patches expected (though `vDSO mremap()` would still require support).
**Cons**:
- The CRIU codebase lacks a dedicated restore daemon, requiring significant rework.
- A 64-bit application can have a 32-bit child, which in turn could parent a 64-bit process. This would require re-executing the native 64-bit CRIU from the 32-bit dummy or subprocess.
- It would be necessary to send process properties, open image file descriptors, and shared memory containing the parsed `ps_tree` to the daemon. The volume of IPC calls would slow down the restoration process.
- Restoration becomes more complex, especially when considering user and PID namespaces.
- Task properties that are erased during `exec()` cannot benefit from optimized inheritance.
- A separate daemon would also be needed for x32.
### Restore with a flag to sigreturn() or arch_prctl()
The initial attempt to implement 32-bit C/R was rejected by the LKML community for several reasons. It involved swapping thread info flags (e.g., `TIF_ADDR32`, `TIF_IA32`, `TIF_X32`), unmapping the native 64-bit vDSO, and mapping the 32-bit vDSO based on a bit in the `rt_sigreturn()` sigframe or a dedicated `arch_prctl()` call.
**Pros**:
- Simple for CRIU: just perform a `sigreturn` with the new bit set or call `arch_prctl` before `sigreturn`.
**Cons**:
- If the 32-bit vDSO on the restoration host differs from the dumped image, the task must be intercepted after `sigreturn` to create jump trampolines (this is simpler with `arch_prctl`).
- Too many potential failure points for a single syscall; overly complex.
- Allowing userspace to swap thread info flags could introduce new race conditions and bugs (e.g., since the `TASK_SIZE` macro depends on `TIF_ADDR32`, memory mapping behavior might become unpredictable).
Following LKML discussions, it was decided to separate personality changes from the vDSO mapping API, remove the `TIF_IA32` flag that distinguished 32-bit from 64-bit tasks, and instead rely on the nature of the syscall (compat, x32, or native).
### Seizing with separate 32-bit and 64-bit parasites
**Pros**:
- No 32-bit calls in the 64-bit parasite and vice-versa.
- Since `ptrace` does not allow setting a 32-bit register set on a 64-bit task (and vice versa), using a parasite of the same nature as the task avoids these limitations.
**Cons**:
- Requires maintaining two or three (for x32) separate parasite blobs.
- Requires complex Makefile macros to build multiple parasites.
- Serializing parasite responses is difficult because argument sizes differ between modes, leading to complex and less readable C macros.
### Current approach
CRIU (a 64-bit process) handles 32-bit (ia32) tasks through a series of architecture-specific transitions:
1. **Architecture Detection**: CRIU uses `ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov)` to detect the task's architecture. The kernel returns different register set sizes depending on the mode: `sizeof(user_regs_struct64)` for native 64-bit tasks and `sizeof(user_regs_struct32)` for 32-bit compatibility mode tasks.
2. **Dumping**: When dumping a 32-bit task, CRIU uses the 64-bit `ptrace` interface. The kernel handles the internal mapping of 32-bit registers into the structure expected by CRIU.
3. **vDSO Handling**: To ensure the restored task uses a vDSO compatible with the current kernel, CRIU uses the `arch_prctl(ARCH_MAP_VDSO_32, addr)` system call (available since kernel v4.8) to map the 32-bit vDSO into the restored process's address space.
4. **Restoration via Sigreturn**: The final restoration of 32-bit registers is performed using a 32-bit `rt_sigreturn` call:
* CRIU prepares a 32-bit signal frame (`rt_sigframe_ia32`) on the target task's stack.
* The CRIU restorer code, running in 64-bit mode, executes a far return (`lretq`) to switch the CPU to 32-bit mode with the `USER32_CS` (0x23) segment selector.
* Once in 32-bit mode, it executes `int $0x80` with the `__NR32_rt_sigreturn` syscall number. The kernel then restores all registers from the 32-bit sigframe and resumes the task in 32-bit mode.
## To-Do
### vsyscall page handling
The `vsyscall` page is an emulated, fixed-address page (`0xffffffffff600000`) used for legacy support. It is not a standard VMA and is marked as `VMA_AREA_VSYSCALL` by CRIU, which avoids dumping or restoring its contents. Since its presence in `/proc/<pid>/maps` depends on kernel configuration (`vsyscall=emulate` or `vsyscall=xonly`), it can introduce noise during ZDTM tests that compare memory layouts. Consequently, tests are often run with `vsyscall=none`.
### Error reporting on x32 binary dumping
Currently, CRIU does not support x32 binaries (64-bit registers with 32-bit pointers). While the infrastructure for 32-bit pointers exists, the specific register handling and vDSO mapping for x32 are not implemented. Attempting to dump an x32 binary should result in an explicit error.
### Removal of TIF_IA32 from the kernel
The `TIF_IA32` thread info flag was historically used to distinguish 32-bit tasks. Kernel efforts (merged in v5.11) have moved towards relying on the nature of the syscall (compat vs. native) rather than a persistent thread flag. This unification simplifies how the kernel and CRIU interact, particularly for tracing tools like uprobes.
CRIU supports checkpointing and restoring kernel-level Asynchronous I/O (AIO) contexts, which are managed via the `io_setup`, `io_submit`, `io_getevents`, and `io_destroy` system calls.
## How CRIU Handles AIO
To successfully checkpoint and restore an AIO context, CRIU manages three primary components:
1. **The AIO Ring Buffer**: This is a memory-mapped area where the kernel and userspace communicate. CRIU identifies these areas by their `[aio]` label in `/proc/pid/maps` or by detecting the specific VMA attributes.
2. **Completed Events**: Events that have finished and are already residing in the ring buffer are dumped as part of the process's memory.
3. **AIO Context State**: This includes the kernel's internal tracking of the ring's head and tail.
### The Restoration Process
The restoration of an AIO ring is complex because the kernel's AIO context ID (the `aio_context_t` value) is an internal pointer that cannot be arbitrarily assigned by userspace. CRIU uses the following strategy to restore it:
1. **New Ring Creation**: The restorer calls `io_setup` to create a fresh AIO ring with the original number of requested events.
2. **Tail Synchronization**: To move the kernel's internal `tail` pointer to the original position, CRIU submits dummy I/O requests (typically writes to `/dev/null`). Since these operations are synchronous for the device, the kernel advances the tail as each request completes.
3. **Head Synchronization**: CRIU manually adjusts the `head` pointer in the ring header to match the state at the time of the dump.
4. **Event Data Restoration**: The original `io_events` data (the completed but unread events) is copied from the dump image into the new ring buffer.
5. **Memory Remapping**: Finally, CRIU uses `mremap` to move the new ring buffer to its original virtual address, ensuring the application can continue using its existing AIO context ID.
## Limitations: In-Flight Events
Currently, **in-flight events** (I/O requests that have been submitted but not yet completed at the time of the dump) are **not supported**.
* **Dumping**: CRIU's parasite code checks for AIO rings but does not currently wait for pending requests to complete. If a request completes during or after the dump, it may lead to data inconsistency or a failed restore.
* **Restoring**: There is no mechanism to re-submit pending I/O requests upon restoration. Applications using AIO should ideally be in a quiescent state (all submitted I/O completed) before being checkpointed.
## See also
* [Memory dumping and restoring](memory-dumping-and-restoring.md)
CRIU provides support for checkpointing and restoring **AppArmor** security profiles and namespaces. This is a critical feature for containerized environments (like Docker, LXC, or Podman) where each container frequently operates under its own set of specialized security policies.
## How CRIU Handles AppArmor
AppArmor integration in CRIU ensures that restored processes continue to operate under the same security constraints as the original processes, while also managing the temporary permissions needed for the checkpointing process itself.
### 1. Checkpointing (Dumping)
During the dump phase, CRIU detects the AppArmor state of each task:
* **Profile Identification**: CRIU captures the active profile name for every thread (e.g., `unconfined`, `docker-default`, or a custom user-defined profile).
* **Namespace and Policy Dumping**: In modern containerized setups, containers often have their own AppArmor namespaces. CRIU walks the `/sys/kernel/security/apparmor/policy/` directory to capture the full hierarchy of namespaces and the raw binary blobs of all loaded policies.
* **Parasite Profile**: To allow the [Parasite Code](parasite-code.md) to perform its necessary inspections (like opening network sockets or reading memory) without being blocked by the application's strict security policy, CRIU temporarily transitions the task into a special, permissive "parasite profile" while it is infected.
### 2. Restoration
Restoring AppArmor state involves re-establishing the security context before the process resumes:
* **Policy Loading**: CRIU uses the `apparmor_parser` utility on the destination host to re-load the policy blobs captured in the image files.
* **Namespace Reconstruction**: It recreates any nested AppArmor namespaces to match the original environment.
* **Profile Re-attachment**: As each process is restored, CRIU ensures it is transitioned back into its original profile (or stack of profiles) using the `aa_change_profile()` interface before the application code begins executing.
## Support for Stacking
Modern AppArmor implementations support **Profile Stacking**, where multiple security profiles are applied to a single process simultaneously (e.g., a container-wide profile plus a per-application profile). CRIU correctly identifies, dumps, and restores these complex stacked configurations.
## Kernel Requirements
Reliable AppArmor C/R requires:
* A kernel with `CONFIG_SECURITY_APPARMOR` enabled and active.
* The `securityfs` filesystem mounted (typically at `/sys/kernel/security`).
* Support for AppArmor policy introspection and namespaces, which is standard in modern distributions like Ubuntu and Debian.
CRIU supports checkpointing and restoring the **Guarded Control Stack (GCS)** feature on ARM64 (AArch64) architectures. GCS is a hardware-assisted shadow stack mechanism designed to prevent return-oriented programming (ROP) attacks by maintaining a protected stack of return addresses.
## How CRIU Handles GCS
GCS support is integrated into CRIU's architecture-specific code for AArch64 (`arch/aarch64/gcs.c`).
### 1. Checkpointing (Dumping)
During the dump phase, CRIU detects if a task has GCS enabled by checking its CPU features and hardware capabilities (`HWCAP_GCS`).
* **State Capture**: CRIU uses `ptrace(PTRACE_GETREGSET, ..., NT_ARM_GCS, ...)` to retrieve the current GCS state.
* **Key Parameters**:
* `gcspr_el0`: The current Guarded Control Stack Pointer.
* `features_enabled`: The GCS configuration flags (e.g., `PR_SHADOW_STACK_ENABLE`).
* **VMA Identification**: CRIU identifies the memory region (VMA) used for the shadow stack, which is marked with special kernel attributes.
### 2. Restoration
Restoring GCS requires carefully re-establishing the shadow stack before the process resumes normal execution.
* **Shadow Stack Mapping**: CRIU uses the `map_shadow_stack` system call to recreate the shadow stack at its original virtual address.
* **Context Setup**: The captured GCS state (`gcspr_el0` and flags) is integrated into the task's **restorer context**.
* **Sigframe Integration**: To ensure a seamless transition, CRIU places a `gcs_context` entry into the signal frame used for the final `sigreturn`. This informs the kernel to switch to the restored shadow stack as the process resumes.
## Kernel Requirements
GCS support in CRIU requires an ARM64 host and a kernel that supports the Guarded Control Stack ABI, typically including:
BPF maps are kernel objects that store data used by BPF programs, typically in the form of key-value pairs. Applications access these maps via file descriptors. Checkpointing and restoring BPF maps involves serializing both their **metadata** and their **data contents**.
## How CRIU Handles BPF Maps
### Metadata Serialization
CRIU collects essential map attributes from several sources:
- **/proc filesystem**: Essential fields such as `map_type`, `key_size`, `value_size`, `max_entries`, and the `frozen` status are parsed from the task's `fdinfo`.
- **BPF System Call**: CRIU uses the `bpf` system call with the `BPF_OBJ_GET_INFO_BY_FD` command to retrieve additional information, including the map name and interface index (`ifindex`).
### Data Serialization
To preserve the map's contents, CRIU relies on batch operations:
- **Dumping**: During the checkpoint stage, CRIU uses `BPF_MAP_LOOKUP_BATCH` to efficiently read all key-value pairs from the map.
- **Restoring**: During the restore phase, CRIU recreates the map and uses `BPF_MAP_UPDATE_BATCH` to repopulate it with the saved key-value pairs.
### Supported Map Types
CRIU currently supports data serialization for the following BPF map types:
- `BPF_MAP_TYPE_HASH`
- `BPF_MAP_TYPE_ARRAY`
For other map types, CRIU may be able to restore the map itself (metadata) but not its contents, depending on kernel support for batch operations on those types.
### Frozen Maps
If a BPF map was marked as read-only (frozen) using `bpf_map_freeze()`, CRIU detects this state from `fdinfo` and reapplies the freeze during restoration after the data has been repopulated.
## To-Do
- **BTF Support**: Serialization and restoration of BPF Type Format (BTF) information associated with maps.
- **Extended Map Types**: Implementation of data serialization for more BPF map types (e.g., `BPF_MAP_TYPE_PERF_EVENT_ARRAY`, `BPF_MAP_TYPE_LPM_TRIE`).
- **Map Extra Data**: Full support for `map_extra` fields introduced in recent kernels (currently only partially parsed with limited restoration).
CRIU provides comprehensive support for checkpointing and restoring Control Groups (CGroups) for both cgroup v1 and cgroup v2.
## Overview
When managing CGroups, CRIU handles three main aspects:
1. **Process Placement**: The specific cgroup sets (a list of controller/path pairs) that each task in the process tree belongs to.
2. **Hierarchy and Properties**: The existing cgroup directory tree, its permissions, and various control properties (e.g., CPU shares, memory limits).
3. **Namespace Boundaries**: Support for CGroup namespaces (`CLONE_NEWCGROUP`), ensuring that the restored tasks have the same view of the cgroup hierarchy.
## Default Behavior
By default, CRIU manages cgroups in **soft mode** (`--manage-cgroups=soft`). In this mode:
* CRIU automatically dumps process cgroup memberships.
* Upon restoration, it attempts to recreate the cgroup hierarchy and restore properties for cgroups that it created.
* If a cgroup already exists, CRIU avoids overwriting its properties to prevent interference with other tasks on the system.
## CGroup V2 Support
CRIU fully supports the unified cgroup v2 hierarchy. Key features include:
* **Global Properties**: Restoration of global v2 attributes such as `cgroup.subtree_control`, `cgroup.max.descendants`, and `cgroup.max.depth`.
* **Process Migration**: Moving tasks between v2 cgroups using `cgroup.procs` (or `cgroup.threads` for threaded controllers).
* **Freezer**: Integrated support for the cgroup v2 freezer mechanism (`cgroup.freeze`).
## CGroup Namespaces
CRIU leverages cgroup namespaces to accurately restore a container's view of the cgroup tree. During restoration:
1. It identifies the cgroup namespace boundary (the path prefix) for each controller.
2. It moves the root task into the appropriate cgroup relative to the host.
3. It calls `unshare(CLONE_NEWCGROUP)` to pin the root of the cgroup namespace to that location, matching the original environment.
## Mountpoints of the "cgroup" Filesystem
CRIU supports dumping and restoring cgroup filesystem mountpoints. However, a significant limitation exists regarding bind-mounted subgroups:
**Root Mount Requirement**: By default, CRIU expects to find the "root" mount of a cgroup controller (where the mount root is `/`) within the dumped mount namespace.
* If a container has only bind-mounted **subgroups** (e.g., `/sys/fs/cgroup/memory/my-container` is bind-mounted to `/sys/fs/cgroup/memory`) without a corresponding root mount of that controller being visible, CRIU may fail the dump.
* This is because CRIU needs to identify the full path of the cgroup relative to the hierarchy root to accurately reconstruct it.
To overcome this, such mounts must often be treated as **external mounts** (`--external mnt[...]`) or the full hierarchy must be made visible to CRIU during the dump.
## CGroups Restoration Strategy
The `--manage-cgroups=MODE` option allows for fine-grained control:
* `none`: Requires cgroups to pre-exist; does not restore properties.
* `props`: Requires cgroups to pre-exist; restores properties from the image.
* `soft` (Default): Restores properties only for cgroups created by CRIU.
* `full`: Always recreates all cgroups and restores all properties.
* `strict`: Recreates all cgroups from scratch; fails if any already exist.
The `--cgroup-yard PATH` option allows CRIU to use a pre-mounted cgroup hierarchy located at `PATH`. This is particularly useful in unprivileged environments where CRIU may not have the `CAP_SYS_ADMIN` capability required to mount cgroup filesystems itself. For every cgroup mount, there should be exactly one directory named after the controller(s) co-mounted there (or "unified" for cgroup v2).
When performing a [live migration](live-migration.md) of a process between hosts, a common challenge is handling IP address changes. While the ideal solution often involves using containers with their own network namespaces and virtual IPs, migrating a service to a different physical IP address is sometimes necessary.
## The Core Problem
TCP connections are identified by a 4-tuple: (Source IP, Source Port, Destination IP, Destination Port). If either IP address changes during migration, the TCP stack on the peer will not recognize the migrated connection and will typically respond with a Reset (RST) or simply ignore the packets.
Consequently, there are three scenarios to consider when changing IPs:
### 1. Listening Sockets
If a server is bound to `0.0.0.0` (INADDR_ANY), it will "just work" after migration, as it will listen on all available interfaces on the new host. However, if the server is bound to a specific IP address that does not exist on the destination host, restoration will fail unless the binding is updated.
**Solutions:**
- **CRIT**: Use the [CRIT](../crit.md) tool to manually edit the `inetsk.img` or `files.img` images to update the binding address.
- **Plugins**: Use the `UPDATE_INETSK` plugin hook (see below) to programmatically change the IP address during restoration.
### 2. In-Flight Connections
These are connections that have been initiated but not yet accepted by the application. CRIU provides the `--skip-in-flight` option to ignore these connections during the dump.
### 3. Established Sockets
These are active connections. Changing the IP address of an established socket is technically possible but will usually break the connection unless specialized network-level translation (like NAT) is used.
**CRIU Solutions:**
- **--tcp-close**: This option tells CRIU to dump established connections but restore them in a closed state. This prevents application-level errors caused by "holes" in the file descriptor table while acknowledging that the specific network connection is terminated.
- **--tcp-established**: Used in combination with IP translation mechanisms (like NAT or proxies), this allows the connection to be restored.
## Programmatic IP Remapping (Plugins)
CRIU provides a plugin hook, `UPDATE_INETSK`, specifically for modifying socket attributes during restoration. A plugin can implement this hook to intercept the restoration of an INET socket and change its source or destination IP addresses.
```c
/* Plugin hook signature in criu-plugin.h */
int cr_plugin_update_inetsk(uint32_t family, uint32_t state, uint32_t *src_ip, uint32_t *dst_ip);
```
By modifying `src_ip` and `dst_ip` within the plugin, you can redirect sockets to new addresses as they are being recreated.
## Summary of Options
| Scenario | Recommendation | CRIU Flag / Tool |
| :--- | :--- | :--- |
| **Old IP not on new host** | Remap local binding | `CRIT` or `UPDATE_INETSK` plugin |
This page describes the high-level design and internal mechanics of the Checkpoint and Restore processes in CRIU.
## Checkpoint
The checkpoint procedure captures the full state of a process tree. It combines information from the Linux kernel's `/proc` filesystem with data extracted directly from the processes' address space.
### 1. Freezing the Process Tree
CRIU begins by identifying the process group leader (via the `--tree` option) and recursively collecting all threads and children. To ensure a consistent snapshot, the entire tree must be "frozen."
* **ptrace**: CRIU uses `PTRACE_SEIZE` followed by `PTRACE_INTERRUPT` to stop tasks without delivering signals that could be visible to the application.
* **Freezer CGroup**: Alternatively, the [Freezer CGroup](freezing-the-tree.md) can be used to freeze all tasks in a single operation.
### 2. Resource Collection (External State)
CRIU gathers state that the kernel exposes via `/proc`:
* **File Descriptors**: Parsed from `/proc/$pid/fdinfo` (which includes positions and flags).
* **Memory Maps**: Captured from `/proc/$pid/smaps` and `/proc/$pid/map_files`.
* **Core State**: Task statistics and basic identifiers from `/proc/$pid/stat`.
### 3. Parasite Injection (Internal State)
Some state (like memory contents and specific credentials) can only be captured from within the process. CRIU uses a technique called **parasite injection**:
1. **Infection**: CRIU uses `ptrace` to inject a small bit of code into the task's instruction stream (at the current `CS:IP`).
2. **Bootstrap**: This code executes an `mmap` syscall to allocate space for the full **parasite blob**.
3. **Execution**: The parasite code runs as a daemon inside the task, communicating with the CRIU coordinator via a Unix socket to dump memory pages and other internal metadata.
### 4. Cleanup
Once the state is captured, CRIU uses `ptrace` to remove the parasite code and restore the original instructions. The processes are then either resumed or killed, depending on the command-line options.
---
## Restore
The restore procedure is essentially the reverse of a checkpoint. CRIU "morphs" itself into the process tree it is restoring through a multi-stage process.
### 1. Resolve Shared Resources
CRIU analyzes the image files to identify resources shared between processes (e.g., shared memory segments, pipes, or inherited file descriptors). It determines which process will "create" the resource and how others will "inherit" it.
### 2. Fork the Process Tree
CRIU calls `fork()` repeatedly to recreate the original process hierarchy. To restore specific PIDs, it uses the `ns_last_pid` interface or the `clone3` system call. At this stage, only process leaders are created; threads are restored later.
### 3. Restore Basic Resources
Each process in the new tree begins restoring its environment:
* **Namespaces**: Joins or creates Network, Mount, UTS, and IPC namespaces.
* **Files and Sockets**: Reopens file descriptors and recreates network sockets.
* **Memory Prep**: Maps anonymous memory regions and fills them with data from the images.
### 4. The Restorer Context
To restore the final memory layout, CRIU must unmap its own code and data. This requires a **restorer blob**:
* **Self-Contained**: The blob is a Position-Independent Executable (PIE) that contains all necessary logic to perform the final `mmap` and `munmap` calls.
* **Non-Conflicting**: It is mapped into a "hole" in the task's address space that does not conflict with either CRIU's current mappings or the task's original mappings.
* **Final Transition**: The process jumps into the restorer blob, which unmaps CRIU, maps the final memory regions, restores timers and credentials, and recreates any additional threads.
### 5. Sigreturn
The very last step of the restorer is to call `sigreturn`. CRIU prepares a special signal frame on the stack that contains the original register state (including the instruction pointer) of the process at the time of the checkpoint. The `sigreturn` syscall tells the kernel to load this state and resume execution of the application code.
*See also: [Restorer Context](restorer-context.md), [Tree After Restore](tree-after-restore.md)*
CRIU and its sub-project **Compel** use specialized binary blobs to execute code in environments where standard libraries and runtime environments are unavailable. These blobs are Position-Independent Executables (PIE) that are converted into C headers for easy integration into the main CRIU binary.
## Why Code Blobs are Necessary
CRIU operates in two primary scenarios that require these specialized environments:
1. **Parasite Code Execution**: During a checkpoint, CRIU injects code into the target process's address space to extract internal state (like memory contents and credentials). This code must be self-contained and PIE-compiled to run at any address.
2. **Restorer Context**: During restoration, the process must unmap its current memory (including CRIU's own code) and map the original memory of the checkpointed application. The code performing these operations must exist in a memory region that does not conflict with the target application's layout.
## Building PIE Code Blobs
The generation of these blobs is handled by the **Compel** utility. The process involves compiling C and assembly source files into a single ELF object and then using the `compel hgen` tool to transform that object into a C header.
### The `compel hgen` Tool
The `hgen` (header generator) tool performs the following tasks:
1. **Relocation Extraction**: It identifies all symbols that require relocation and creates a structured `compel_reloc` array.
2. **Binary Data Conversion**: It converts the allocated ELF sections (code and data) into a static C byte array.
3. **Bootstrap Initialization**: It generates a setup function (e.g., `parasite_setup_c_header`) that populates a `parasite_blob_desc` structure, which CRIU uses to manage the blob's lifecycle.
The build system follows these steps to generate the headers:
1. **Compilation**: Source files (like `parasite.c` or `restorer.c`) are compiled with PIE flags (`-fpie`, `-ffreestanding`, `-nostdlib`).
2. **Linking**: Object files are linked into a single `.built-in.o` file using a specialized linker script (`compel-pack.lds.S`) that organizes sections into a layout suitable for a standalone blob.
3. **Header Generation**: The `compel hgen` command is executed on the linked object to produce the final `-blob.h` header.
DMTCP implements checkpoint/restore at the library level. To use it, an application must be launched with the DMTCP library dynamically linked from the start. This library intercepts library calls, builds an internal shadow database of the process state, and forwards requests to `glibc` or the kernel.
**Key Characteristics of DMTCP:**
* **No Kernel Patches**: Works on standard kernels without requiring specific features.
* **Library Level**: Intercepts calls at the userspace level, which can introduce performance overhead.
* **PID Virtualization**: Since the kernel does not traditionally allow setting a specific PID during fork, DMTCP "fools" the application by intercepting `getpid()` and returning a fake value. This can be problematic if the application accesses `/proc` using its real PID.
* **Limited API Coverage**: May not support all kernel APIs (e.g., `inotify` support is limited).
In contrast, **CRIU** does not require pre-loading libraries. It uses standard kernel interfaces (extended where necessary for C/R) to transparently capture and restore arbitrary applications.
## BLCR (Berkeley Lab Checkpoint/Restart)
BLCR is a system-level checkpointer designed primarily for High Performance Computing (HPC) and MPI jobs. It is implemented as a loadable kernel module.
**Key Characteristics of BLCR:**
* **Kernel Module**: Requires a specific GPL-licensed kernel module.
* **HPC Focused**: Optimized for CPU and memory-intensive batch jobs.
* **Limited Scope**: Traditionally lacks support for complex modern features like namespaces, containers, or diverse socket types.
## PinPlay
PinPlay is a checkpointing tool built on top of Intel's PIN binary instrumentation tool. It is primarily used for deterministic replay and architectural simulation. It records architectural register state and memory pages, often focusing on reducing runtime for simulators.
## OpenVZ (In-Kernel)
Legacy OpenVZ (RHEL6 and earlier) featured an in-kernel C/R implementation. While highly efficient and robust for its time, it required a heavily patched kernel. CRIU was developed as the "user-space" successor to this technology, moving the logic out of the kernel to improve maintainability and facilitate upstream adoption.
CRIU employs a specialized multi-stage process to preserve Copy-on-Write (COW) sharing of private anonymous memory mappings during restoration. This prevents the memory duplication that would occur if each process's memory were restored independently, thereby significantly reducing the memory footprint of the restored process tree.
## The Problem
When a process calls `fork()`, the Linux kernel optimizes memory usage by sharing private anonymous mappings between the parent and child. Physical pages are only duplicated (COW) when one of the processes modifies them.
Traditional checkpointing captures each process's memory separately. If restored naively (by mapping and filling each VMA individually), the kernel would allocate separate physical pages for the parent and child, even for pages that were originally shared. This leads to a massive increase in physical memory usage upon restoration.
## CRIU's COW Restoration Strategy
To keep COW mappings intact, CRIU performs restoration in a way that mimics the original `fork()` behavior.
### 1. Identifying COW Candidates
Before forking the process tree, CRIU analyzes the memory maps of all tasks:
* It compares each task's VMAs with those of its parent.
* Two VMAs are identified as COW candidates if they have identical start/end addresses, the same protection flags (e.g., `PROT_READ`, `PROT_WRITE`), and belong to the same executable.
* This mapping is stored internally, marking which VMAs are "inherited" from a parent.
### 2. Pre-mapping and Filling
During restoration, processes are created in a specific order:
1. **Root VMA Population**: If a VMA is the "root" of a COW set (it is not inherited), the restoring task maps it and fills it with data from the image files.
2. **Inheritance via Fork**: When a task forks a child, the child automatically inherits the parent's memory mappings via the standard kernel COW mechanism.
3. **Content Verification**: The child then iterates through its own memory images:
* It compares the page contents in the image with the data already present in its inherited memory (which it got from the parent).
* If the contents match exactly, the physical page remains shared with the parent.
* If they differ (meaning the page was modified in either process after the original fork), the child overwrites the page with the data from its image, triggering a kernel COW event for that specific page.
### 3. Cleaning Up (madvise)
A parent may contain pages that were unmapped or modified in the child process. To ensure the child's memory layout is perfectly accurate:
* CRIU maintains a bitmap of pages touched during the content verification stage.
* After all pages are processed, CRIU uses `madvise(MADV_DONTNEED)` on any pages that exist in the inherited VMA but were not present in the child's dump images. This effectively "punches holes" in the child's VMA to match its original state while preserving the sharing of other pages.
## Current Limitations
* **Reparenting to Init**: If a process was reparented to the system `init` (PID 1) and that `init` process is not part of the checkpointed process tree, CRIU cannot identify the parent's VMAs, and COW sharing will not be restored for that process.
* **VMA Movement**: If a VMA was moved (e.g., via `mremap`) after the original `fork()`, CRIU's current address-based matching algorithm will fail to identify it as a COW candidate.
## See Also
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
This article explains the fundamental differences between CRIU and DMTCP (Distributed MultiThreaded Checkpointing), focusing on their architectural approaches to process capture and restoration.
## Architectural Approach
### DMTCP: Library-Level Interception
DMTCP implements checkpoint/restore at the **userspace library level**. To use it, an application must be launched with the DMTCP library dynamically linked (`LD_PRELOAD`).
* **Mechanism**: The library intercepts library calls (e.g., `glibc` wrappers for syscalls), builds an internal shadow database of the process state, and then forwards requests to the kernel.
* **Implications**: This approach can introduce performance overhead due to proxying. Only applications compatible with the DMTCP library can be reliably dumped. Furthermore, DMTCP may not support all kernel APIs; for instance, complex features like `inotify` or specific socket types may lack sufficient proxies.
### CRIU: Kernel-Level Integration
CRIU, by contrast, operates primarily from **outside the process** using standard kernel interfaces (extended where necessary for C/R).
* **Mechanism**: CRIU uses tools like `ptrace`, `/proc`, and specialized system calls (e.g., `kcmp`, `map_files`) to transparently capture the process state without requiring pre-loaded libraries.
* **Implications**: It can checkpoint and restore virtually any application, provided the kernel supports the required features. It requires a relatively modern kernel version but offers much deeper integration with system resources like namespaces and cgroups.
## PID Handling and Virtualization
Restoring a process tree often requires restoring specific Process IDs (PIDs).
* **DMTCP "Fake" PIDs**: Because the kernel does not traditionally allow userspace to request a specific PID during `fork()`, DMTCP "fools" the application. It intercepts the `getpid()` call and returns a fake value that matches the original PID. This is highly dangerous, as the application may see inconsistent information in the `/proc` filesystem (where directories are named by the *real* PID).
* **CRIU Real PIDs**: CRIU restores the **actual PID** of the process. It achieves this by using the `ns_last_pid` interface or the modern `clone3` system call with a specified PID. This ensures that the restored process has the exact same identity as the original, with no inconsistencies in `/proc` or other kernel interfaces.
## Summary
DMTCP is often easier to deploy on older kernels since it doesn't require specific kernel support, but it suffers from the inherent limitations and risks of userspace interception. CRIU is the more robust and transparent solution for modern Linux systems, offering faithful restoration of the entire process environment.
This document explains the internal mechanisms CRIU uses to capture the state of opened file descriptors (FDs).
## Linux File Objects: Inodes, Dentries, and Files
In the Linux kernel, an opened file is represented by a chain of three distinct objects:
1. **Inode**: Contains metadata (owner, type, size) and pointers to the actual data on disk.
2. **Dentry (Directory Entry)**: A helper object used to resolve file paths. An inode can have multiple dentries if hard links exist.
3. **File (or "File Description")**: Represents an active handle to a dentry/inode pair. It maintains state such as the current file position (`pos`) and access flags.
Crucially, **file descriptors** are per-task integers that point to these shared "File" objects. When a task calls `fork()`, the child's FDs point to the same "File" objects as the parent's.
## How CRIU Collects FD Information
Dumping FDs requires CRIU to collect state from both the kernel's `/proc` filesystem and the file objects themselves.
### 1. Identifying Open FDs
CRIU reads `/proc/$pid/fd/` and `/proc/$pid/fdinfo/` to determine which FD numbers are currently open and to retrieve their basic properties (position and flags).
### 2. Retrieving File Objects (SCM_RIGHTS)
To perform deeper inspection (like `fstat` or `ioctl`), CRIU needs a local copy of the file descriptor. It achieves this by:
* Injecting **parasite code** into the target task.
* Commanding the parasite to send the FDs to the CRIU coordinator via a Unix domain socket using the `SCM_RIGHTS` mechanism.
### 3. Detecting Shared Files (gen_id and kcmp)
To minimize image size and avoid redundant dumps, CRIU must identify if FDs in different tasks (or even the same task) point to the same underlying "File" object. It uses a two-stage optimization:
1. **gen_id**: CRIU calculates a "generation ID" based on the file's device ID, inode number, and current position. If two FDs have different `gen_id`s, they are guaranteed to be different.
2. **kcmp**: If `gen_id`s match, CRIU uses the `kcmp()` system call (with the `KCMP_FILE` flag) to definitively determine if the two descriptors refer to the same kernel "File" object.
## Image Storage
CRIU stores FD information in a two-tier structure:
### The `fdinfo-$id.img` Image
This per-task image maps task-specific FD numbers to global **File IDs**. Each entry contains:
* `fd`: The numeric descriptor in the task.
* `id`: A unique identifier for the underlying file object.
### Specialized File Images
The actual state of the file objects is stored in specialized images based on their type:
* `reg-files.img`: Regular files (includes the path).
* `pipes.img`: Pipes and FIFOs.
* `unixsk.img` / `inetsk.img`: Sockets.
* `signalfd.img`, `eventfd.img`, `epoll.img`, etc.
This separation allows CRIU to efficiently handle shared files: multiple `fdinfo` entries can point to a single entry in a specialized file image.
This page provides answers to common questions and technical insights into CRIU's behavior and limitations.
## General Questions
### Q: Why does CRIU dump parts of read-only code mappings?
**A**: Even if a mapping (like the code section of `/usr/bin/something`) is marked as read-only, it may still contain "dirty" pages that CRIU must dump. This typically happens due to **Copy-on-Write (COW)** events during dynamic linking, relocation patching, or if the process modified its own code via `mprotect` and `ptrace`.
### Q: How can I verify that my system is ready for CRIU?
**A**: Use the built-in check tool:
```bash
criu check --extra
```
This will verify that your kernel has all the necessary features (like `kcmp`, `ns_last_pid`, etc.) enabled. Additionally, running the [ZDTM Test Suite](zdtm-test-suite.md) is the best way to confirm functional correctness on your specific hardware and software stack.
### Q: Is it possible to change the IP address during live migration?
**A**: Yes, but with caveats. Since TCP connections are identified by their IP/Port 4-tuple, changing the IP will normally break established connections.
- If you can tolerate connection resets, use the `--tcp-close` flag.
- For listening sockets, you can use the `UPDATE_INETSK` plugin hook or the `CRIT` tool to remap addresses.
- For seamless migration, virtual IPs or network-level NAT are required. See [Changing IP Addresses](change-ip-address.md) for more details.
### Q: Why does restore fail with a "PID mismatch" error?
**A**: This occurs because the PID CRIU is trying to restore is already in use by another process on the system.
- **Solution**: The most common way to avoid this is to run the restored process inside a fresh **PID namespace**. This ensures that the PID range is entirely available to CRIU.
- **Internal Note**: CRIU uses the `ns_last_pid` kernel interface or the modern `clone3` system call to request specific PIDs during restoration.
### Q: Why does dump fail with "Cannot dump half of a stream unix connection"?
**A**: This usually happens when one end of a Unix domain socket is held by a process *outside* the process tree being checkpointed. CRIU cannot capture the state of the "external" peer, so it cannot safely restore the connection unless the socket is explicitly marked as external via the `--external unix[ino]` option.
---
## Testing (ZDTM)
### Q: Why do my ZDTM tests fail with "Permission Denied" even when run as root?
**A**: The `zdtm.py` test runner executes many sub-tests as a non-privileged user to verify CRIU's behavior in unprivileged environments. If your specific test requires root privileges, you must add `'flags': 'suid'` to the test's `.desc` file.
---
## Containers and Docker
### Q: Why can't I restore a Docker container onto a different image?
**A**: CRIU checkpoints the state of the processes, but it does **not** checkpoint the underlying filesystem. The process images contain paths to files that must exist exactly as they did during the dump.
- **Solution**: To restore a container, you must ensure the filesystem state is identical. In Docker, this often involves using `docker commit` to create an image of the container's filesystem at the moment of the checkpoint.
- **Modern Tools**: Container engines like Podman or newer versions of Docker/RunC handle this integration more seamlessly by managing the filesystem snapshots alongside the CRIU state.
CRIU uses a sophisticated state machine to restore file descriptors (FDs) across a process tree, handling shared files, complex dependencies, and inter-process synchronization.
## Master and Slave Descriptors
In the Linux kernel, multiple FDs can refer to the same underlying "File Description." CRIU mirrors this by categorizing FDs into **Masters** and **Slaves**:
1. **Master**: For each unique file object, one FD is designated as the master. This process is responsible for the actual `open()`, `socket()`, or `pipe()` system call that recreates the object.
2. **Slaves**: All other FDs referring to the same object are slaves. They do not perform the creation call themselves; instead, they receive the file descriptor from the master.
3. **Transport (SCM_RIGHTS)**: CRIU uses Unix domain sockets and the `SCM_RIGHTS` mechanism to "send" file descriptors from the master process to slave processes.
## Per-Process Restore Loop
Each task in the process tree executes a loop (`open_fdinfos`) to restore its descriptors. The core of this loop is the `file_desc_ops->open()` method.
### The `open()` State Machine
The `open()` method for a master file can return one of three values:
* **0 (Success)**: The file is fully restored.
* **1 (In Progress)**: The file has been opened (or the process has started opening it), but it cannot be completed yet due to a dependency on another file. The loop will call this method again in the next iteration.
* **-1 (Failure)**: An error occurred, and restoration must abort.
### Early FD Distribution
To maximize parallelism, a master can return a valid FD in the `new_fd` argument even if it returns `1` (In Progress). This allows CRIU to immediately distribute the FD to all slave processes via `SCM_RIGHTS`, even before the master has finished its own restoration steps (e.g., a connected Unix socket waiting for its peer).
## Inter-Process Synchronization
CRIU uses **futexes** and a specialized event mechanism to coordinate between processes:
* **set_fds_event(pid)**: Signals a task that a file it was waiting for (as a slave) is now available or that a dependency has changed.
* **wait_fds_event()**: Causes a task to sleep until it receives a notification.
* **FLE Stages**: Each descriptor entry (`struct fdinfo_list_entry` or `fle`) transitions through stages: `INITIALIZED` -> `OPEN` -> `RESTORED`.
## Key Dependencies
The engine must resolve complex dependencies between different file types:
1. **TTYs**: A slave TTY can only be fully restored after its master peer is active.
2. **Unix Sockets**: A connected socket must wait for its peer to `bind()` to its address before it can `connect()`.
3. **Epoll**: An epoll FD can be created immediately, but adding FDs to its interest list must wait until those FDs are themselves restored.
4. **Pipes and Socketpairs**: These calls create two FDs at once. One is treated as the primary master, and the second is distributed to the appropriate task (which might be the same task or a different one).
## Technical Notes
* **Service FDs**: CRIU maintains its own internal FDs (for images, logs, etc.) in a "protected" range to avoid conflicts with the application's FDs during restoration.
* **Ordering**: Descriptors are generally restored in ascending order of their FD number to improve efficiency, though dependencies can override this order.
While Linux aims for a uniform filesystem interface, several filesystems have unique behaviors ("peculiarities") that require specialized handling in CRIU to ensure accurate checkpointing and restoration.
## BTRFS: Virtual Device Numbers
When you `stat()` a file on BTRFS, the kernel often reports a **virtual device ID** (`st_dev`) that is unique to that specific subvolume or snapshot. However, other kernel interfaces, such as `/proc/$pid/mountinfo` or the `sock_diag` subsystem, may report the **physical device ID**.
**Problem**: CRIU cannot rely on simple `st_dev` comparisons to identify which mount a file belongs to, as the virtual and physical IDs will mismatch.
**Solution**: CRIU performs userspace path-to-device resolution. It analyzes `/proc/$pid/mountinfo` to build a mapping between virtual and physical IDs, allowing it to correctly resolve file locations. See `mount.c:phys_stat_resolve_dev()`.
**Workaround**: In some environments (like Podman), disabling Copy-on-Write for the container storage (`chattr +C`) can mitigate some BTRFS-related complexities.
## NFS: "Silly Rename" and Unlinked Files
NFS handles unlinked but open files differently than local filesystems. When a file is unlinked while still open, the NFS client performs a **"Silly Rename"**, renaming the file to something like `.nfsXXX` instead of truly removing it.
**Problem**: CRIU's standard logic for detecting unlinked files (checking if `st_nlink == 0`) fails on NFS because the "silly renamed" file still has a link count of 1.
**Solution**: CRIU explicitly checks if a file resides on an NFS mount. If it does, it examines the filename for the `.nfs` prefix. If both conditions match, CRIU treats the file as "opened and unlinked," capturing its contents into the image as a **ghost file**. See `files-reg.c:nfs_silly_rename()`.
## OverlayFS: Path Inconsistencies and Link-Remap
OverlayFS, the standard for modern container engines, has several known issues:
1. **Path Mismatches (Pre-v4.2)**: On older kernels, `/proc/$pid/fd/` and `/proc/$pid/fdinfo/` could report paths that did not include the OverlayFS mountpoint. CRIU detects OverlayFS mounts and manually corrects these paths using information from the mount table.
2. **linkat() Failures**: In OverlayFS, the `linkat()` system call fails with `ENOENT` if the file being linked resides on a **lower layer** (read-only layer) and has been unlinked from the upper layer.
* **CRIU Response**: When a "link-remap" (linking a deleted file back to the filesystem) fails on OverlayFS, CRIU automatically falls back to dumping the file as a **ghost file** (copying its contents into the image).
## AUFS: Branch Path Leakage (Legacy)
AUFS (mostly superseded by OverlayFS) has a bug where `/proc/$pid/maps` reveals the path of a file within its internal **branch** directory instead of its visible path within the AUFS mount.
**Solution**: CRIU identifies AUFS mounts, reads the branch configuration from `sysfs`, and "fixes" the paths in the memory map to ensure the file can be correctly located during restoration. See `sysfs_parse.c:fixup_aufs_vma_fd`.
## See also
* [How Hard is it to Open a File?](how-hard-is-it-to-open-a-file.md)
This document describes the possible states a process tree can end up in after a successful CRIU **dump** or **restore** operation.
## Supported Final States
CRIU supports three primary final states for the process tree:
1. **Running (`TASK_ALIVE`)**: The processes continue execution as normal.
2. **Stopped (`TASK_STOPPED`)**: The processes are left in a stopped state (equivalent to receiving `SIGSTOP`).
3. **Dead (`TASK_DEAD`)**: The processes are terminated (equivalent to receiving `SIGKILL`).
## Controlling the Final State
You can specify the desired final state using the following command-line options:
* `--leave-running`: Forces the process tree to continue running after the operation.
* `--leave-stopped`: Forces the process tree to remain stopped after the operation.
### Default Behavior for `criu dump`
By default, `criu dump` terminates the process tree (**Dead**).
**Rationale**: Leaving a process tree running after a full dump is risky. If the processes continue to run, they will likely modify the filesystem, network state, or shared memory. These changes can make the captured image inconsistent or impossible to restore later, as the system state will no longer match the process's internal state at the moment of the dump.
* **Exceptions**: The `pre-dump` command always enforces the **Running** state, as its purpose is to capture memory changes while the application continues to operate.
### Default Behavior for `criu restore`
By default, `criu restore` resumes the process tree (**Running**).
**Rationale**: The primary goal of restoration is typically to resume the application's work immediately.
* **Debugging**: Using `--leave-stopped` during restoration can be extremely useful for debugging. It allows you to inspect the restored process tree (e.g., via `/proc` or a debugger) before it begins executing any code.
## Resuming a Stopped Tree
If a process tree was left in the **Stopped** state (either by dump or restore), you can resume its execution by sending a `SIGCONT` signal to all processes in the tree.
For complex process trees, the [pstree_cont.py](https://github.com/checkpoint-restore/criu-scripts/blob/master/pstree_cont.py) script (available in the `criu-scripts` repository) can be used to safely resume the entire hierarchy by targeting the root PID.
Before CRIU can begin checkpointing, it must ensure that the entire process tree is completely "immobilized." This prevents tasks from changing their state (e.g., opening files, creating children, or receiving network packets) while the snapshot is being taken. This freezing process must be transparent to the application, meaning it should not observe any disruption or unexpected signals.
CRIU employs two primary methods to achieve this:
## Capturing with ptrace
The most common method for freezing a tree is using the Linux `ptrace` interface. Unlike traditional debuggers that might send disruptive signals like `SIGSTOP`, CRIU uses a more modern, non-invasive approach:
1. **SEIZE**: CRIU calls `ptrace(PTRACE_SEIZE, pid, ...)` for every task in the tree. This "attaches" to the process without stopping it or delivering any signals.
2. **INTERRUPT**: Once seized, CRIU sends a `ptrace(PTRACE_INTERRUPT, pid, ...)` command. This causes the kernel to stop the task at the next possible opportunity (typically upon entering or exiting a syscall or being preempted).
3. **WAIT**: CRIU then waits for the task to enter the `TRAP_STOP` state. This state is invisible to the task's own signal handling logic, ensuring transparency.
By seizing every task in the tree, CRIU ensures that no task can resume execution or fork new children during the dump.
## Using Freezer CGroups
For large process trees or environments where `ptrace` might be restricted or inefficient, CRIU can use the Linux **Freezer CGroup**. This allows the kernel to freeze an entire group of processes in a single, atomic operation.
CRIU supports both versions of the freezer:
### CGroup v1 Freezer
* **Mechanism**: CRIU identifies the freezer cgroup containing the process tree and writes `FROZEN` to the `freezer.state` file.
* **Handling Inconsistency**: Historically, the v1 freezer could be unreliable, sometimes getting stuck in a `FREEZING` state. CRIU includes "kludges" to handle this, such as periodically retrying the freeze command or briefly thawing and re-freezing the group to kick the kernel's internal state machine.
### CGroup v2 Freezer
* **Mechanism**: In the unified cgroup v2 hierarchy, CRIU writes `1` to the `cgroup.freeze` file.
* **Verification**: It then monitors the `cgroup.events` file, waiting for the `frozen 1` event to signal that all processes in the sub-hierarchy have successfully stopped.
**Note**: Even when using a freezer cgroup, CRIU still attaches to the tasks via `ptrace` after they are frozen. This is necessary to perform internal inspections, such as extracting register states and injecting parasite code.
CRIU supports checkpointing and restoring `inotify` and `fanotify` instances. These mechanisms allow applications to monitor filesystem events (like file creation, modification, or deletion).
## The Challenges of FSNotify C/R
Restoring an fsnotify instance is inherently difficult because the kernel does not provide a direct way to retrieve the original path of a watched object (the "watchee"). Furthermore, the event queues themselves pose consistency risks.
### 1. Identifying the Watchee
When an application adds a watch (via `inotify_add_watch`), the kernel associates the watch with an **inode**, but it does not store the **path** used to create it. To restore the watch, CRIU must find a valid path to that specific inode.
* **Open by Handle**: CRIU first attempts to use `open_by_handle_at()`. If the filesystem supports file handles, CRIU captures the handle during the dump and uses it to re-open the inode during restoration without needing the original path.
* **Irmap (Inode Reverse Mapping)**: If file handles are unavailable, CRIU uses the [Irmap](irmap.md) engine to scan the filesystem and find a path that leads to the target inode.
### 2. Event Queue Consistency
If there are pending events in the fsnotify queue at the time of the dump, CRIU cannot currently "peek" at them or safely migrate them.
* **Dropped Events**: During a dump, CRIU checks if the fsnotify file descriptor has data. If it does, CRIU emits a warning: `The ... inotify events will be dropped`. These events are lost, and the application must be prepared to handle this gap in its event stream.
* **Spurious Events**: The process of checkpointing and restoring itself can trigger new filesystem events. For example, creating or deleting **ghost files** (temporary files used to restore unlinked but open files) can generate `IN_CREATE` or `IN_DELETE` events that the application will see upon resumption.
### 3. Ghost Files and Circular Dependencies
A "ghost file" is a file that was deleted by the application but is still held open. During restoration, CRIU must recreate these files. This action itself generates notify events, potentially confusing applications that monitor the directories where these ghost files are temporarily placed.
## Support for Fanotify
CRIU also supports `fanotify`, including:
* **Inode Marks**: Similar to inotify, these target specific files or directories.
* **Mount Marks**: Fanotify can monitor entire mount points. CRIU identifies the mount ID and restores the mark on the corresponding mount in the restored namespace.
## Current Strategy: "Chopping the Knot"
Due to the complexity of perfectly migrating event queues, CRIU's current strategy is:
1. **Warn and Drop**: Acknowledge that pending events are lost.
2. **Restore the Watches**: Ensure the application continues to receive *new* events after restoration.
3. **Namespace Integration**: Correctly map mount-level fanotify marks within their respective mount namespaces.
# The Complexity of Re-opening Files during Restore
Re-creating an open file descriptor during restoration is far more complex than simply calling `open(path, flags)`. This article explores the numerous edge cases CRIU must handle to faithfully reconstruct the file state.
## 1. Basic Opening
At its simplest, a file is defined by its path and access mode:
```c
int fd = open(f->path, f->mode);
```
However, this is only the beginning of the process.
## 2. FIFOs and Blocking
A standard `open()` call on a FIFO (named pipe) can hang indefinitely if there is no corresponding reader or writer on the other end. CRIU avoids this by first opening the FIFO with `O_RDWR` (to ensure at least one of each is present) and then using `dup2` to establish the final descriptor with the correct original flags.
## 3. Unlinked but Open Files (Ghost Files)
Linux allows files to be deleted while they are still open. These "invisible" files no longer have a path in the filesystem.
* **link-remap**: If the file still has other hard links elsewhere, CRIU may create a temporary link to it to allow it to be re-opened via a path.
* **Ghost Files**: If the link count is zero, CRIU captures the entire content of the file during the dump. During restore, it recreates this file in a temporary location, opens it, and then unlinks it to match the original state.
## 4. Directories and Hard Links
Directories cannot be hard-linked. If a directory was unlinked, CRIU must recreate it, open it, and then remove it. For files with multiple hard links that were all deleted, CRIU must ensure they all point back to the same physical inode upon restoration, requiring careful tracking of "temporary" paths and user-space reference counts.
## 5. Mount Namespaces and Chroot
The same path (e.g., `/etc/passwd`) might refer to entirely different files depending on the mount namespace or `chroot` environment of the process.
* **mnt_id**: CRIU records the mount ID for every file during the dump.
* **open_ns_root**: During restoration, CRIU uses file descriptors referring to the root of the specific mount namespace to ensure that `openat()` targets the correct physical file, regardless of the restorer's current root.
## 6. File Ownership and Signals (fown)
Files can have an associated "owner" (a PID or PGID) that receives signals (like `SIGIO` or `SIGPOLL`) when I/O events occur.
* **F_SETOWN_EX**: CRIU restores this ownership using the extended owner structure.
* **UID Switching**: Setting the owner of a file may require specific privileges. CRIU may temporarily switch its effective UIDs during the `fcntl` call to satisfy kernel permission checks if the file owner differs from the restorer.
* **F_SETSIG**: The specific signal number to be delivered is also faithfully restored.
## 7. Position and Flags
* **Lseek**: The current byte offset (`pos`) is restored using `lseek`.
* **Flag Sanitization**: Certain flags (like `O_CREAT`, `O_EXCL`, `O_TRUNC`) only make sense during the initial creation of a file. CRIU strips these before the restore-time `open()` to avoid accidentally creating or truncating existing files.
* **O_PATH**: Files opened with `O_PATH` are handled as pure path references; they do not have positions, ownership, or data access.
## 8. The Final Step: Descriptor Planting
Once a file is successfully opened (at a temporary descriptor number assigned by the kernel), it must be moved to the exact numeric descriptor the application expects (e.g., FD 42). This is achieved via `dup2()`, but requires coordination when descriptors are shared across a process tree.
*See also: [How to assign needed file descriptor to a file](how-to-assign-needed-file-descriptor-to-a-file.md)*
Once a file is [opened during restoration](how-hard-is-it-to-open-a-file.md), it often needs to be moved to a specific numeric file descriptor (FD) and potentially shared with other tasks in the process tree. This document explains how CRIU coordinates this process.
## The Basic Mechanism: `dup2`
In Linux, the `dup2(oldfd, newfd)` system call is the standard way to assign a file to a specific descriptor number. CRIU uses this to move a newly opened file from its temporary descriptor (assigned by the kernel) to the target descriptor expected by the application.
```c
int fd = open_a_file(f->file);
dup2(fd, f->target_fd);
close(fd);
```
## Handling Multiple Descriptors for One File
A single task may have multiple FDs referring to the same kernel "File Description" (e.g., a shell where FD 0, 1, and 2 all point to the same TTY). CRIU handles this by identifying the unique file object, opening it once, and then calling `dup2()` for every target FD slot the application expects.
## Sharing Files Across the Process Tree
Files are frequently shared between processes. While these files were originally inherited via `fork()`, CRIU must often distribute them between processes that do not have a direct parent-child relationship during the restore phase.
### Master and Slave Descriptors
For every unique file object in a checkpoint:
1. **The Master**: One task is designated as the "master" for that file. It is responsible for the actual system call that recreates the object (e.g., `open()`, `socket()`, or `pipe()`).
2. **The Slaves**: All other tasks that share the same file are "slaves." They do not create the file themselves.
### Transport via SCM_RIGHTS
CRIU uses Unix domain sockets to "send" descriptors from the master process to slave processes using the `SCM_RIGHTS` mechanism.
**The Workflow:**
1. **Master Opens**: The master task creates the file object.
2. **Master Sends**: The master sends the resulting file descriptor to each slave task over a dedicated transport socket.
3. **Slave Receives**: The slave task waits on its transport socket, receives the FD, and uses `dup2()` to plant it into the correct numeric slot.
## Solving the Coordination Problem
Distributing thousands of descriptors across a complex process tree requires careful management to avoid deadlocks and descriptor collisions.
### 1. Transport Sockets
CRIU creates abstract Unix sockets for each process to receive descriptors. The names are uniquely generated using the PID and a `criu_run_id` (e.g., `\0x/crtools-fd-123-abcdef`) to ensure that multiple simultaneous CRIU runs on the same host do not interfere with each other.
### 2. Deterministic "Master" Selection
To prevent circular dependencies (e.g., Task A waiting for Task B while B waits for A), CRIU uses a deterministic priority system to select the master. Typically, the task with the highest priority—usually the one closest to the root of the tree or with the lowest PID—is chosen to open and distribute the file.
### 3. Descriptor Collisions
A task's target FDs may conflict with the internal "service" FDs CRIU uses for images, logs, or transport sockets. CRIU resolves this by:
* **Service FD Range**: Restricting CRIU's own FDs to a specific range.
* **Dynamic Relocation**: If a target FD slot is occupied by an active service FD, CRIU moves the service FD to a new, free slot using `dup()` before planting the application's FD.
## Complex Dependencies
Some file types have inherent dependencies. For instance, an `epoll` descriptor cannot be fully restored until the files it monitors are already opened and their numeric descriptors are known. CRIU's file restoration engine handles this via a multi-pass state machine, where some files are opened but their full restoration is deferred until their dependencies are satisfied.
# Re-opening Files without Paths (open_by_handle_at)
Occasionally, CRIU encounters an open file descriptor for which the kernel no longer maintains a path. This document explains how CRIU uses file handles and Inode Reverse Mapping (Irmap) to reconstruct these "nameless" files.
## When Paths Are Lost
The most common scenario for path loss occurs with **fsnotify** (inotify and fanotify) instances.
When an application calls `inotify_add_watch(path)`, the kernel:
1. Resolves the path to an **inode**.
2. Attaches a watch generator to that inode.
3. Immediately forgets the path used to create the watch.
The resulting file descriptor points to the fsnotify instance, which knows *which* inode it is watching but not *where* that inode lives in the filesystem hierarchy. Because the dentry (directory entry) cache can be shrunk by the kernel at any time, the path information is often permanently lost to userspace.
## Strategy 1: open_by_handle_at
Linux provides a specialized system call, `open_by_handle_at()`, designed for userspace NFS servers. It allows opening a file using a **File Handle**—a filesystem-specific blob of bytes that uniquely identifies an inode.
### The Handle mechanism
1. **Dumping**: CRIU reads the file handle for a watch from `/proc/$pid/fdinfo/$fd`. (CRIU developers upstreamed patches to the Linux kernel to ensure this information is exposed).
2. **Restoring**: During restoration, CRIU takes this handle and calls `open_by_handle_at()`. This returns an `O_PATH` file descriptor pointing to the original inode, even if its original path is unknown.
3. **Re-attaching**: CRIU then uses this `O_PATH` descriptor to re-establish the inotify or fanotify watch, effectively "tricking" the kernel into watching the correct inode.
## Strategy 2: Irmap (Inode Reverse Mapping)
Not all filesystems support file handles (e.g., some older or specialized filesystems). In these cases, CRIU must resort to a brute-force approach called **Irmap**.
The Irmap engine maintains a cache that maps `(device, inode)` pairs back to their filesystem paths.
1. **Scanning**: Irmap recursively scans "known" directories (like configuration paths or application homes) and records every name-to-inode mapping it finds.
2. **Lookup**: When CRIU needs a path for a specific inode, it queries the Irmap cache.
3. **Pre-dump Integration**: To minimize the performance impact of filesystem scanning, CRIU can perform this scan during a **pre-dump** while the application is still running. The results are saved to an `irmap-cache.img` file and reused during the final dump.
## Filesystem Specifics
* **Tmpfs**: This filesystem pins its dentries in memory. For tmpfs, paths are almost always available via `/proc` and do not require handles or Irmap.
* **OverlayFS**: Due to its layered nature, OverlayFS can have complex handle behaviors. CRIU includes specific logic to navigate these layers during handle resolution.
This directory contains technical documentation detailing the internal implementation of CRIU, the kernel APIs it leverages, and the complex algorithms used to achieve checkpoint and restore of various Linux resources.
## Core Architecture & Lifecycle
* [Checkpoint and Restore Overview](checkpointrestore.md): High-level view of the C/R process.
* [Freezing the Process Tree](freezing-the-tree.md): How CRIU stops the application using the freezer cgroup or signals.
* [Parasite Code](parasite-code.md): Injection and execution of code within the victim's address space.
* [Restorer Context](restorer-context.md): The environment in which the restorer blob executes.
* [Stages of Restore](stages-of-restoring.md): Detailed breakdown of the multi-stage restoration process.
* [Final States](final-states.md): The state of processes after restore.
* [Technologies Used](technologies.md): Overview of kernel technologies CRIU depends on.
* [Kerndat](kerndat.md): How CRIU probes and caches kernel feature support.
## Memory Management
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md): The primary algorithms for memory C/R.
* [Memory Changes Tracking](memory-changes-tracking.md): Using dirty bits (soft-dirty) for iterative migration.
* [Pagemap Cache](pagemap-cache.md): Optimizing access to `/proc/pid/pagemap`.
* [Copy-on-Write Memory](copy-on-write-memory.md): Handling shared and private COW mappings.
* [Shared Memory](shared-memory.md): Restoration of SysV IPC and POSIX shared memory.
* [Memory Images Deduplication](memory-images-deduplication.md): Saving space in image files.
* [Optimizing Pre-dump Algorithm](optimizing-pre-dump-algorithm.md): Strategies for minimizing downtime.
* [Userfaultfd](userfaultfd.md): Lazy migration and post-copy restoration.
## Files, Mounts & I/O
* [Dumping Files](dumping-files.md): General overview of file descriptor C/R.
* [How hard is it to open a file?](how-hard-is-it-to-open-a-file.md): The complexities of reconstructing file states.
* [How to open a file without open() syscall](how-to-open-a-file-without-open-system-call.md): Using `linkat` and other tricks for inaccessible files.
* [How to assign needed FD to a file](how-to-assign-needed-file-descriptor-to-a-file.md): Re-mapping FDs to match original values.
* [Invisible Files](invisible-files.md): Handling unlinked but open files.
* [FD Info Engine](fdinfo-engine.md): Parsing `/proc/pid/fdinfo`.
* [Service Descriptors](service-descriptors.md): Managing CRIU's internal FDs to avoid collisions.
* [Mount Points](mount-points.md): Basic mount restoration.
* [Mount V2](mount-v2.md): Modern mount restoration using `open_tree` and `move_mount`.
* [Mounts V2 Virtuozzo](mounts-v2-virtuozzo.md): Extensions for Virtuozzo-specific mount features.
* [Filesystem Peculiarities](filesystems-pecularities.md): Handling `/dev`, `/proc`, `sysfs`, etc.
* [IRM](irmap.md): Inode-to-path mapping (irmap).
* [KCMP Trees](kcmp-trees.md): Using `kcmp` to deduplicate shared resources.
* [Validate Files on Restore](validate-files-on-restore.md): Ensuring file consistency.
* [FSNotify](fsnotify.md): Checkpointing inotify and fanotify marks.
In Linux, a file can remain accessible to a process even if it no longer has a visible path in the filesystem. This occurs when a file is unlinked (deleted) while still open or when its path becomes inaccessible due to mount shadowing. This document explains how CRIU detects and reconstructs these "invisible" files.
## How Files Lose Their Paths
### 1. Unlinked while Open
The most common case is when an application opens a file and then immediately deletes it:
```c
int fd = open("/tmp/secret", O_RDWR);
unlink("/tmp/secret");
```
The file data persists in the kernel as long as the file descriptor remains open, but it no longer exists in the filesystem directory structure.
### 2. Virtual Filesystem Deletion
On virtual filesystems like `/proc`, if a process dies, its entries (e.g., `/proc/$PID/cmdline`) disappear. However, if another process still has an open file descriptor to one of these entries, the file remains alive but "nameless."
### 3. Mount Shadowing (Overmounts)
If a process opens a file in `/mnt/data` and then a new filesystem is mounted over `/mnt`, the original file becomes inaccessible via its path.
## CRIU's Detection and Reconstruction Strategies
CRIU uses the `/proc/$pid/fd/` and `/proc/$pid/fdinfo/` interfaces to identify open files and their expected paths.
### Ghost Files (Link Count = 0)
If a file has a link count of zero (`st_nlink == 0`), it is truly deleted.
* **Dumping**: CRIU reads the entire content of the file and stores it within the image directory as a "ghost file."
* **Restoring**: During restoration, CRIU recreates the file in a temporary location, opens it, and then immediately unlinks it to restore the original unlinked state.
* **Optimization**: For large sparse files, CRIU can use the `--ghost-fiemap` option to only capture the data blocks, significantly reducing image size.
### Link-Remap (Link Count > 0)
If a file has a positive link count but its expected path is missing or points to a different file, it means the specific name used to open the file was deleted, but other hard links still exist.
* **Strategy**: CRIU uses `linkat()` with the `AT_EMPTY_PATH` flag to create a temporary name for the file on the same filesystem. This allows it to be re-opened via a path during restoration.
* **Option**: This behavior is enabled via the `--link-remap` flag.
### Virtual File Remap (The PID Helper)
For deleted `/proc` entries, CRIU cannot use ghost files or `linkat()`. Instead:
1. It records the PID of the original process that the `/proc` entry referred to.
2. During restoration, it creates a temporary **TASK_HELPER** process with that specific PID.
3. The restored application opens the `/proc/$PID/...` entry of this helper.
4. The helper is terminated once all restoration tasks are complete.
### Filesystem-Specific Handling
* **NFS**: CRIU detects "Silly Rename" files (`.nfsXXX`) and handles them via the link-remap mechanism.
* **OverlayFS**: Since `linkat()` may fail on OverlayFS if the file resides on a read-only lower layer, CRIU automatically falls back to the ghost file strategy in these cases.
* **Devpts**: Files on `devpts` (like PTYs) are managed by the kernel and are restored using specific PTY master/slave allocation logic rather than file-based reconstruction.
## Technical Details
* **--ghost-limit**: By default, CRIU limits ghost files to **1 MB** to prevent excessive disk usage. This can be increased via the `--ghost-limit` option.
* **--evasive-devices**: Allows CRIU to proceed even if a character or block device path has changed, provided the device numbers (`st_rdev`) match.
Irmap is CRIU's engine for resolving an `(inode, device)` pair back into a filesystem path. This is primarily required for restoring **fsnotify** (inotify and fanotify) instances, which internally reference inodes but do not preserve the paths used to create them.
## The Problem
When an application creates an inotify watch, the kernel resolves the path to an inode and attaches the watch to it. The original path string is then discarded by the kernel. During a checkpoint, CRIU can see which inode is being watched but needs a valid path to recreate that watch during restoration.
## How Irmap Works
Irmap uses a combination of predefined hints and brute-force scanning to build a reverse mapping cache.
### 1. Heuristic Hints
CRIU starts by scanning "known" locations where applications typically place watches, such as:
- `/etc` (configuration files)
- `/var/log` (log monitoring)
- `/var/spool`
- D-Bus and Polkit service paths (`/usr/share/dbus-1/services`, etc.)
- `/lib/udev`
- The root directory (`/`)
### 2. User-Defined Scan Paths
Users can provide additional directories to scan via the command line to help CRIU find application-specific files more quickly:
```bash
criu dump --irmap-scan-path /path/to/my/app ...
```
These paths are prioritized and scanned before the default hints.
### 3. Caching and Pre-dump
Scanning large filesystems can be slow and resource-intensive. To mitigate this:
- **irmap-cache.img**: Scan results are stored in this image file within the images directory.
- **Pre-dump Optimization**: CRIU can perform the irmap scan during a `pre-dump` while the application is still running. This populates the cache early, significantly reducing the time the application must remain frozen during the final dump.
- **Validation**: On subsequent runs, CRIU loads the cache and re-validates entries individually (checking if the inode/device still matches the path) rather than performing a full re-scan.
## Support for Filesystems
* **Standard Filesystems**: Works well on most local filesystems (ext4, xfs, etc.).
* **Tmpfs**: Paths are generally available via `/proc` and don't strictly require Irmap, though it can still be used.
* **OverlayFS**: Irmap has historically had difficulties with OverlayFS due to how inodes are reported across different layers. In modern kernels, **open_by_handle_at** (leveraging file handles exposed in `/proc/$pid/fdinfo`) is the preferred and more reliable alternative to Irmap.
CRIU must frequently determine if system resources (such as file descriptions, memory mappings, or namespaces) are shared between different processes. While some objects have unique kernel-provided IDs (like inode numbers for files on disk), many do not. This document explains how CRIU uses the `kcmp()` system call and red-black trees to efficiently detect these shared objects.
## The Challenge
Comparing every resource in every process against every other process would result in $O(N^2)$ complexity, where $N$ is the total number of resources (e.g., 100 tasks with 100 files each = 10,000 files, or 50 million pairs). This is prohibitively slow.
## The Solution: `kcmp()` and Pointer Comparison
The `kcmp()` system call identifies whether two kernel objects are the same. Crucially, its return value is not a simple boolean; it returns the result of an internal kernel pointer comparison:
* **0**: The objects are identical.
* **1**: The first object's pointer is "less than" the second.
* **2**: The first object's pointer is "greater than" the second.
* **-1**: Error.
This ordering information allows CRIU to use **red-black trees** to sort and search for objects with $O(N \log N)$ complexity.
## Two-Level Red-Black Trees
To further optimize performance and minimize the number of expensive `kcmp()` system calls, CRIU uses a two-level tree structure:
### Level 1: Fast ID (genid)
CRIU first calculates a "generation ID" (`genid`) using cheap, locally available metadata. For regular files, this is derived from the device ID, inode number, and current file position.
* Objects are inserted into a primary red-black tree ordered by `genid`.
* If two objects have different `genid`s, they are guaranteed to be different, and no system call is needed.
### Level 2: Sub-tree (kcmp)
If two objects have identical `genid`s, they *might* be the same.
* CRIU then descends into a sub-tree associated with that `genid`.
* In this sub-tree, objects are ordered using the `kcmp()` system call.
* If `kcmp()` returns 0, the objects are confirmed as shared.
## Supported Object Types
CRIU uses `kcmp()` for various object types, including:
* **KCMP_FILE**: Individual file descriptions.
* **KCMP_VM**: Virtual memory address spaces.
* **KCMP_FILES**: The entire file descriptor table.
* **KCMP_FS**: Filesystem information (umask, root, cwd).
* **KCMP_SIGHAND**: Signal handler tables.
* **KCMP_IO**: I/O context.
* **KCMP_SYSV_SEM**: System V semaphore undo lists.
* **KCMP_EPOLL_TFD**: Specific descriptors within an epoll interest list.
**Kerndat** is a CRIU module responsible for detecting the capabilities and features of the currently running Linux kernel. Since CRIU's functionality depends heavily on specific kernel system calls and behaviors, runtime detection is essential for ensuring compatibility and selecting the most efficient algorithms.
## Feature Detection
CRIU performs a wide array of checks during initialization. These include:
* **System Call Availability**: Checking for `kcmp()`, `userfaultfd()`, `memfd_create()`, `clone3()`, `openat2()`, `membarrier()`, and more.
* **Namespace Support**: Detecting Time namespaces, CGroup namespaces, and namespace-specific identifiers.
* **Architecture-Specific Quirks**: Identifying known CPU bugs or features, such as the x86 FPU/XSAVE ptrace bug.
The results of these checks are stored in a global `kdat` structure, which other CRIU modules query to determine how to proceed during dump and restore operations.
## Persistent Caching
Executing hundreds of kernel feature checks can be time-consuming. To speed up subsequent CRIU invocations, the results are cached on disk.
* **Cache Location**:
* **Root**: `/run/criu.kdat` (typically stored on `tmpfs` to ensure it is cleared on reboot).
* **Non-root**: `$XDG_RUNTIME_DIR/criu.kdat`.
* **Lifecycle**: CRIU attempts to load this cache during `kerndat_init()`. If the cache is missing or stale (e.g., if the CRIU binary has been updated with new checks), CRIU performs a full detection and saves the new results back to the cache file.
## Kerndat vs. Inventory
It is important to distinguish between **kerndat** and the **inventory image** (`inventory.img`):
* **Kerndat**: Captures the capabilities of the **host kernel**. It is system-wide and typically survives across different CRIU operations on the same host.
* **Inventory**: Captures critical metadata about a **specific checkpoint**. It is stored within the images directory and includes the CRIU version used for the dump, the host's LSM type (SELinux/AppArmor), and the root task's original IDs.
## Inspection
To see the features detected by CRIU on your current system, use the check command:
```bash
criu check --extra
```
This command triggers a kerndat initialization and prints the status of various required and optional kernel features, allowing you to verify that your environment is ready for CRIU.
Mac-VLAN is a Linux network driver that allows creating multiple virtual interfaces with unique MAC addresses on top of a single physical interface. These virtual interfaces act as standalone devices on the network, each with its own IP and MAC address.
## Checkpoint and Restore of Mac-VLAN
CRIU identifies Mac-VLAN interfaces by monitoring netlink messages (specifically `RTM_NEWLINK`) and inspecting their attributes.
### 1. Checkpointing
During a dump, CRIU extracts the following attributes for each Mac-VLAN device:
- **Parent Interface**: The physical device (or "upper" link) that the Mac-VLAN is built upon (identified via `IFLA_LINK`).
- **Mode**: The specific Mac-VLAN operational mode (e.g., `bridge`, `private`, `vepa`, `passthru`), extracted from `IFLA_MACVLAN_MODE`.
- **Flags**: Any additional configuration flags associated with the interface (`IFLA_MACVLAN_FLAGS`).
- **MAC Address**: The unique hardware address of the virtual interface.
### 2. Restoration
To recreate a Mac-VLAN interface exactly as it was, CRIU performs the following:
- **Link Creation**: It sends an `RTM_NEWLINK` netlink message with the kind set to `"macvlan"`, specifying the original mode and the link to the parent device.
- **Index Preservation**: To ensure that any application sockets bound to the interface index remain valid, CRIU uses the `IFLA_NEW_IFINDEX` attribute. This allows CRIU to request the exact same interface index that the device possessed before the checkpoint. (This kernel feature was originally developed specifically to support CRIU).
- **Namespace Migration**: Once created, the interface is moved into the target network namespace for the restored process.
## External Interface Mapping
Since the parent physical interface may have a different name or index on the destination host during migration, CRIU provides the `--external` option to map these dependencies:
```bash
# Example mapping of an internal macvlan interface to a host physical interface
criu restore --external macvlan[eth0]:phys0 ...
```
This tells CRIU that the Mac-VLAN interface which was originally attached to `eth0` should now be attached to the physical interface `phys0` on the current host.
Memory changes tracking (also known as "dirty memory tracking") is a critical feature in CRIU that enables efficient **live migration** with minimal downtime. By identifying and capturing only the memory pages that have been modified since a previous snapshot, CRIU can perform iterative dumps while the application continues to run.
## The Problem: Memory Dump Latency
During a standard checkpoint, CRIU freezes the process tree and dumps its entire memory state to disk. For memory-intensive applications (like large databases), this process can take several seconds, during which the application is completely unresponsive. This "freeze time" is directly proportional to the amount of memory used by the application.
## The Solution: Iterative Dumps
To minimize freeze time, CRIU supports an iterative migration scheme:
1. **Initial Pre-dump**: Capture a full snapshot of the application's memory while it is still running.
2. **Subsequent Pre-dumps**: Periodically capture only those pages that have been modified (made "dirty") since the last pre-dump.
3. **Final Dump**: Freeze the processes and capture the final set of dirty pages. Since most memory was already transferred in previous steps, the final freeze time is significantly reduced.
## Kernel Mechanisms for Tracking
CRIU relies on two primary kernel mechanisms to track dirty pages:
### 1. The Soft-Dirty Bit
Linux maintains a "soft-dirty" bit for each Page Table Entry (PTE).
* **Resetting**: CRIU enables tracking by writing "4" to `/proc/$pid/clear_refs`, which clears the soft-dirty bit for all pages in the task's address space.
* **Tracking**: Any subsequent write to a page causes the kernel to set its soft-dirty bit.
* **Reading**: CRIU identifies dirty pages by reading the bit from the process's `/proc/$pid/pagemap` interface.
### 2. ioctl(PAGEMAP_SCAN)
Reading the entire `/proc/$pid/pagemap` file can be slow for very large address spaces. Modern kernels (v6.7+) support the `PAGEMAP_SCAN` ioctl, which allows CRIU to:
* **Efficient Scanning**: Identify dirty pages across a large address space in a single kernel call.
* **Filtering**: Directly filter for specific page categories (e.g., only dirty and present pages).
* **Atomic Reset**: Optionally clear the soft-dirty bit while scanning, ensuring no writes are missed between scanning and resetting.
CRIU automatically detects and uses `PAGEMAP_SCAN` if available, falling back to manual `/proc` parsing on older kernels.
## Implementation in CRIU
Iterative migration is managed through the `pre-dump` command:
1. **Chained Images**: Each pre-dump creates a set of image files in a new directory. These directories are linked together using the `--prev-images-dir` option.
2. **Consolidated Restore**: During restoration, CRIU traverses the chain of images from newest to oldest. For any given memory address, it restores the most recent version of the page found in the image stack.
3. **Page Server**: To avoid writing iterative dumps to disk, they can be sent over the network to a **page server** on the destination host.
Dumping and restoring the memory of a process tree is one of the most critical and complex tasks performed by CRIU. This document details the mechanisms, optimizations, and kernel interfaces involved in this process.
## The Virtual Memory Layout (VMAs)
A process's address space is composed of several Virtual Memory Areas (VMAs). CRIU identifies these areas by parsing `/proc/$pid/smaps` and `/proc/$pid/map_files/`.
* **Metadata**: Each VMA's start address, end address, protection flags (read, write, execute), and sharing status (private or shared) are recorded in the `mm-$id.img` file.
* **Backing Store**: CRIU also records whether a VMA is anonymous (backed by RAM/swap) or file-backed.
## The Dumping Process
Capturing memory contents while maintaining consistency and performance requires a multi-stage approach.
### 1. Parasite Injection
CRIU cannot efficiently read a process's private memory from the outside. Instead, it injects **parasite code** into the target task. This code runs within the task's own address space and context, allowing it direct access to all memory regions.
### 2. Zero-Copy Dumping (vmsplice)
To transfer memory from the parasite to the CRIU dumper with minimal overhead, CRIU uses a zero-copy mechanism:
1. **Pipe Setup**: CRIU creates a pipe and sends one end to the parasite via a Unix domain socket.
2. **vmsplice**: The parasite uses the `vmsplice()` system call with the `SPLICE_F_GIFT` flag. This effectively "gifts" the memory pages to the kernel's pipe buffer without copying the data in userspace.
3. **Splice to Image**: The CRIU dumper then uses `splice()` to move the data from the pipe directly into the image file (`pages-$id.img`) or to a network socket (for the page server).
### 3. Page Deduplication and Skipping
CRIU avoids dumping unnecessary data to save time and space:
* **Unchanged File Pages**: Read-only, file-backed pages (like library code) that have not been modified are not dumped. CRIU simply records the file and offset to re-map them during restoration.
* **Dirty Tracking**: Using the **soft-dirty bit** (or `PAGEMAP_SCAN`), CRIU can identify and dump only those pages that have changed since a previous pre-dump.
---
## The Restoration Process
Restoring memory involves reconstructing the exact address space layout the application had at the moment of the checkpoint.
### 1. Re-mapping VMAs
During the early stages of restoration, each process calls `mmap()` to recreate its VMAs based on the data in `mm-$id.img`.
* **Anonymous Memory**: Mapped as private and anonymous.
* **File Mappings**: Re-mapped from their original files on disk.
### 2. Filling Memory Contents
CRIU then repopulates the mappings with the data stored in the `pages-$id.img` files. For efficiency, CRIU uses its own optimized I/O routines to read the images and fill the memory regions.
### 3. COW Preservation
CRIU uses a specialized strategy to ensure that memory shared via `fork()` (Copy-on-Write) remains shared after restoration. This minimizes the total physical memory footprint of the restored process tree. See [COW Memory](copy-on-write-memory.md) for details.
## Advanced Migration Techniques
* **Page Server**: During live migration, memory pages are sent over the network to a page server on the destination host, avoiding expensive disk I/O.
* **Lazy Migration (Userfaultfd)**: CRIU can restore a process immediately without its memory and then load pages on demand as the application accesses them. This is powered by the `userfaultfd` kernel feature and is essential for reducing initial downtime.
During iterative migration, CRIU produces multiple snapshots of a process's memory. Since most memory pages remain unchanged between iterations, saving every page in every snapshot would result in significant disk space waste and increased migration time. CRIU uses several deduplication techniques to address this.
## How Deduplication Works
Deduplication relies on identifying pages that are identical to those in a previous snapshot (the "parent" image).
### 1. The `in_parent` Flag
The `pagemap-$id.img` file describes the virtual memory layout. Each entry (`pagemap_entry`) can include an `in_parent` flag:
* **If `false`**: The page's contents are stored in the current `pages-$id.img` file.
* **If `true`**: The page's contents are identical to the one in the parent image. CRIU does not write the data to the current `pages-$id.img`, saving both disk space and I/O time.
### 2. Detection via Soft-Dirty
During a `pre-dump`, CRIU uses the kernel's **soft-dirty bit** to identify which pages have been modified.
* If a page was present in the previous iteration and its soft-dirty bit is **not set**, CRIU knows the content remains unchanged.
* It marks the page as `in_parent` in the current pagemap image and skips dumping its data.
## Auto-Deduplication (`--auto-dedup`)
CRIU provides an advanced `--auto-dedup` mode that optimizes both the dumping and restoration processes.
### During Dump
When `--auto-dedup` is enabled during a dump, CRIU actively manages the relationship between the current and parent image sets to ensure maximum deduplication efficiency. It traverses the previous images to verify which regions can be safely referenced rather than re-dumped.
### During Restore (Disk Space Optimization)
A unique and powerful feature of `--auto-dedup` during restoration is **online disk space reclamation**:
* As CRIU reads pages from the `pages-$id.img` files to restore the process's memory, it uses the `fallocate(FALLOC_FL_PUNCH_HOLE)` system call on the image files.
* This "punches holes" in the images, effectively freeing the underlying physical disk blocks as soon as the data has been loaded into RAM.
* This is critical for systems with limited disk space when restoring from a large number of iterative pre-dumps, as it prevents the total image size from exceeding the available storage.
## Implementation Details
* **Image Chaining**: Deduplication requires a chain of images established via the `--prev-images-dir` option, allowing CRIU to look back through multiple layers of snapshots.
* **Sparse File Support**: The hole-punching mechanism leverages the host filesystem's support for sparse files, ensuring that the restored environment remains efficient.
CRIU provides deep support for capturing and reconstructing Linux mount namespaces and the complex hierarchies of mount points within them. This includes support for bind mounts, shared propagation, and external dependencies.
## Key Information Captured
For every mount namespace, CRIU parses `/proc/$pid/mountinfo` to extract:
1. **Mount Hierarchy**: The parent-child relationships between mount points.
2. **Filesystem Details**: Device IDs, filesystem types, and the mount source.
3. **Root and Target**: The specific directory within the filesystem being mounted and its destination in the process's view.
4. **Propagation State**: Whether a mount is `shared`, `slave`, `private`, or `unbindable`.
5. **Mount Options**: Flags such as `ro`, `nodev`, `noexec`, and `nosuid`.
## The Restoration Challenge
Restoring mounts is one of CRIU's most difficult tasks because it must recreate the exact same state that the kernel built up over time. This requires:
* **Dependency Sorting**: Mounts must be recreated in the correct order (e.g., a parent must exist before its child can be mounted).
* **Source Resolution**: CRIU must be able to access the original filesystem source.
* **Propagation Reconstruction**: Shared and slave relationships must be established in the correct sequence to ensure future mount events propagate as expected.
## Mount V2: The Modern Engine
CRIU includes an advanced restoration engine called **Mount V2** (`--mount-v2`). This engine uses a more robust algorithm to handle:
* **Complex Overmounts**: Scenarios where multiple mounts are stacked on the same directory.
* **Circular Dependencies**: Resolving cases where mounts depend on each other in non-trivial ways.
* **Namespace Sharing**: Efficiently handling processes that share the same mount namespace.
## External and Auto-detected Mounts
Sometimes, the source of a mount point is located outside the container or process tree being checkpointed (e.g., a host directory bind-mounted into a container).
### 1. External Mounts (`--external`)
Users can manually specify how to handle these external dependencies by mapping the mount's identifier to a path on the destination host:
CRIU can often automatically identify external bind mounts by comparing the mount points in the target process with those in its own mount namespace. This simplifies migration by reducing the need for manual mapping.
## Common Issues
* **Unsupported Filesystems**: Some specialized or virtual filesystems may not support standard checkpointing. These often require plugins or must be marked as external.
* **Hidden Sources**: If a bind mount's source is overmounted and no longer visible, CRIU may fail to identify how to recreate it without the Mount V2 engine or manual hints.
> **Note**: This document describes an early design iteration for mount restoration. The current and much more advanced implementation is documented in [Mount V2](mount-v2.md).
For detailed information on the modern mount restoration algorithm, including the use of detached mounts and `move_mount`, please refer to:
Introduced in CRIU v3.16, **Mount V2** is a sophisticated restoration engine that leverages modern Linux kernel APIs to handle complex mount hierarchies, propagation groups, and overmounts with high reliability.
## Why Mount V2 was Necessary
The original mount restoration mechanism (Mount V1) relied on sequential, path-based `mount()` calls. This approach had several critical flaws:
1. **Overmount Sensitivity**: If a directory was already covered by another mount, performing a path-based mount on it could fail or target the wrong filesystem.
2. **Circular Dependencies**: Resolving mounts that depend on each other in non-linear ways was difficult and often resulted in ordering failures.
3. **Propagation Complexity**: Establishing `shared` and `slave` relationships required creating dummy mount points and performing specific sequences of `mount --make-shared/slave` calls, which was fragile in complex scenarios.
## How Mount V2 Works
Mount V2 moves away from path-based mounting, instead using **File Descriptor-based** mounting provided by newer kernel system calls.
### 1. Detached Mounts
CRIU creates each required mount as a **detached mount**. These mounts exist in the kernel but are not yet attached to any visible path in the filesystem.
* **New Filesystems**: Created using `fsopen()` and `fsmount()`.
* **Bind Mounts**: Created using `open_tree()` with the `OPEN_TREE_CLONE` flag to create an unattached clone of an existing path.
### 2. Precise Propagation Grouping
Using the `move_mount()` syscall with the `MOVE_MOUNT_SET_GROUP` flag (introduced in kernel v5.15), CRIU can explicitly assign a detached mount to a specific **shared or slave propagation group**. This eliminates the need for dummy mounts and ensures that the propagation state is perfectly restored as recorded in the images.
### 3. Tree Construction via File Descriptors
CRIU constructs the entire mount hierarchy by attaching child mounts to their parents using their respective file descriptors. Since this happens "off-line" (outside of any mount namespace), it is immune to path shadowing, path resolution errors, or overmounting issues.
### 4. Atomic Final Attachment
Once the complete hierarchy is assembled as a tree of detached mounts, CRIU performs a final `move_mount()` to attach the root of this reconstructed tree into the target mount namespace at the desired destination path.
CRIU automatically detects these features during the [Kerndat](kerndat.md) phase. It will fall back to the older Mount V1 engine if these calls are unavailable, though many modern container layouts now effectively require Mount V2 for a successful restore.
The Mount V2 engine (originally developed by Virtuozzo and later merged into upstream CRIU) is designed to resolve complex issues with restoring sharing groups, over-mounted files, and cross-namespace bind mounts. This document provides a technical breakdown of its operation.
## 1. Mount Image Processing Stage
During initialization, CRIU processes the mount images for all namespaces to build an internal model of the filesystem state:
- **Hierarchy Construction**: Build a per-namespace mount tree based on parent IDs.
- **Bind Grouping**: Group mounts by superblock equality into "bind" lists to identify shared underlying filesystems.
- **Sharing Groups**: Organize shared and slave groups into a tree structure (e.g., where a parent's `shared_id` matches a child's `master_id`).
- **The Root Yard**: Create a helper mount (`root_yard_mp`) at a temporary location (e.g., `/tmp/.criu.mntns.XXXXXX/`). All mount trees from all namespaces are initially merged as subdirectories of this "root yard."
## 2. Pre-Fork Mounting Stage
This stage is executed from the init task in a dedicated "service" mount namespace before the target process tree is forked:
1. **Plain Mounting**: CRIU walks the merged mount tree and creates all mounts in a "plain" (unattached) and "private" state.
2. **Source Resolution**: For each mount, CRIU identifies its source (a real filesystem, a bind mount from another already-mounted superblock, or an external source).
3. **Cross-Namespace Handling**: By maintaining all mounts within a single service namespace during this stage, CRIU can easily handle bind mounts that cross namespace boundaries.
## 3. Propagation and Shared Group Restoration
CRIU restores complex propagation relationships using modern kernel APIs:
- **Slavery and Sharing**: For each sharing group, CRIU identifies the "master" mount. It uses the `move_mount()` system call with the `MOVE_MOUNT_SET_GROUP` flag (or the legacy `MS_SET_GROUP` mechanism) to establish slave/shared relationships precisely as they existed during the dump.
- **Settings Replication**: Once the sharing state is established for the primary mount in a group, all other members of the group inherit these settings.
## 4. Namespace Transition and Final Positioning
For each target mount namespace being restored:
1. **Unshare**: CRIU calls `unshare(CLONE_NEWNS)` to create a fresh, empty mount namespace.
2. **Tree Positioning**: Move the "plain" mounts from the root yard into their final hierarchical positions within the new namespace using `move_mount()`.
3. **Pivot Root**: Execute `pivot_root()` to switch to the new namespace root, effectively hiding the temporary "yard" and finalizing the mount hierarchy.
## 5. Post-Fork Fixups
Certain mounts cannot be fully restored until the process tree is established:
- **Delayed Procfs**: `proc` mounts for nested PID namespaces must wait until the target PID namespace is created. CRIU enters these namespaces after forking to perform the final mounts.
- **Internal Yards**: In some cases, temporary `tmpfs` mounts ("internal yards") are used within a namespace to hold mounts that must be moved or adjusted after the process tree is fully alive.
Pre-dumping is the process of capturing dirty memory pages while an application continues to run, aiming to minimize the final "freeze time" during live migration. CRIU provides two primary modes for pre-dumping: `read` and `splice`.
## Traditional vs. Optimized Pre-dump
### The `read` Mode (Traditional)
In this mode, CRIU uses the `process_vm_readv` system call to read memory from the target process.
* **Workflow**: Tasks are briefly frozen to identify dirty pages and reset the soft-dirty bit, then resumed. CRIU then reads the pages from the running process's address space.
* **Challenge**: Reading memory while a process is running can lead to minor inconsistencies if the process modifies a page *while* it is being read (see [Memory Consistency](#memory-consistency) below). Furthermore, `process_vm_readv` requires the target process to be alive and its memory mappings to remain stable during the read.
### The `splice` Mode (Optimized & Default)
The `splice` mode (enabled via `--pre-dump-mode=splice`) uses a zero-copy "gift" mechanism to further reduce freeze time and improve reliability.
#### How `splice` Mode Works:
1. **Brief Freeze**: CRIU seizes the tasks and injects the parasite code.
2. **vmsplice "Gifting"**: The parasite identifies dirty pages and calls `vmsplice()` with the `SPLICE_F_GIFT` flag. This flag tells the kernel that the process is "giving" these pages to a pipe.
3. **Immediate Resume**: Once the `vmsplice()` calls are complete (which is extremely fast as no data is actually copied), the parasite is removed, and the tasks are resumed immediately.
4. **Parallel Draining**: While the tasks are running, the main CRIU process "drains" the data from the pipes and writes it to the image files or sends it to the page server.
#### Why `splice` is Better:
* **Minimized Downtime**: The "freeze" duration is reduced to just the time needed for the parasite to execute the `vmsplice()` system calls, rather than the time needed to transfer memory data over the network or to disk. This scheme relies entirely on `vmsplice()` being extremely fast. Because the target process is frozen during these calls, minimizing this duration is critical to the primary goal of pre-dumping: reducing process downtime during live migration and making the migration process almost invisible to the application.
* **Zero-Copy Transfer**: By gifting pages directly from the target process to the pipe, `splice` mode avoids copying memory to CRIU user-space buffers (unlike `read` mode which uses `process_vm_readv` to copy data). While this zero-copy mechanism does not use COW (meaning intermediate dumps can be inconsistent if pages are modified after resume), CRIU's iterative design handles this inconsistency (see below) while maximizing transfer performance.
## Memory Consistency
Because the target process is resumed while CRIU is still writing the memory data (in both `read` and `splice` modes), intermediate pre-dump images may contain inconsistent memory states.
This inconsistency is expected and handled by CRIU's iterative design:
1. **Tracking Changes**: CRIU uses the kernel's soft-dirty tracker to monitor memory writes after the process is resumed.
2. **Subsequent Dumps**: Any page modified after it has been pre-dumped is marked dirty again and will be captured in the next pre-dump iteration or during the final dump.
3. **Restoring Consistency**: During restore, CRIU applies the dump images in sequence (from oldest pre-dump to the final dump). The final dump is taken while the process is fully frozen, ensuring that the final state of all memory pages is consistent.
## Usage
The optimized `splice` mode is the default in modern CRIU. It can be explicitly requested using the `--pre-dump-mode` option:
When dumping the memory of a process, CRIU must frequently query the kernel to determine which virtual memory pages are currently present in RAM, swapped out, or modified (dirty). This information is typically retrieved from the `/proc/$pid/pagemap` file. However, reading and parsing this file repeatedly for every Virtual Memory Area (VMA) is inefficient. To solve this, CRIU implements a high-performance **Pagemap Cache**.
## The Performance Problem
The `/proc/$pid/pagemap` file is a 64-bit-per-page binary stream. For a process with a large address space, this file can be several megabytes in size. While a single sequential read is fast, CRIU needs this data across multiple stages of the dump (e.g., initial size estimation, private memory dumping, shared memory dumping, and iterative pre-dumps). Performing multiple full reads and frequent `lseek()` calls into this file introduces significant overhead, especially for applications with thousands of small VMAs.
## Implementation Details
The pagemap cache (`struct pmc`) optimizes access through several advanced techniques:
### 1. Sliding Window Caching
Instead of reading the entire pagemap at once, CRIU uses a sliding window (typically **2MB** in size, defined as `PMC_SIZE`).
* When a VMA is accessed that is not currently in the cache (a cache miss), the cache "refills" itself by reading the pagemap for the required range.
* **Greedy Prefetching**: If the current VMA is small, the cache tries to fill the remainder of the 2MB window by pre-reading information for subsequent, adjacent VMAs. This significantly reduces the total number of `read()` system calls and minimizes the overhead of kernel-side page table walks.
### 2. ioctl(PAGEMAP_SCAN) Integration
On modern kernels (v6.7+), the pagemap cache leverages the `PAGEMAP_SCAN` ioctl. This interface is far more efficient than the legacy `/proc` file:
* **Bulk Retrieval**: It allows CRIU to fetch information for multiple, non-contiguous page ranges in a single kernel call.
* **Kernel-Side Filtering**: CRIU can instruct the kernel to only return information for specific categories of pages (e.g., pages that are both present in RAM and marked as "soft-dirty"), further reducing the amount of data transferred and processed in userspace.
### 3. Cache Invalidation
To ensure consistency, the pagemap cache is per-process and is strictly managed:
* The cache is typically populated while the target process is **frozen** to ensure a stable view of memory.
* The cache is invalidated whenever the process state might have changed or when the dumper transitions between different memory processing phases.
## Debugging and Control
The pagemap cache can be disabled for troubleshooting or performance comparison by setting the `CRIU_PMC_OFF` environment variable.
## See also
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
The **parasite code** is a specialized binary blob that CRIU injects into the address space of a target process during a checkpoint. Its primary purpose is to extract internal task state—such as private memory contents, credentials, and signal handlers—that is not available via standard kernel interfaces like `/proc`.
## The Infection Process
Infection is a multi-stage operation managed by the **Compel** sub-project, leveraging the `ptrace` system call to take control of the target process.
### 1. Seizing the Task
CRIU stops the target task using `PTRACE_SEIZE` followed by `PTRACE_INTERRUPT`. This ensures a non-disruptive stop without delivering signals to the application, maintaining transparency.
### 2. Bootstrap Payload
CRIU identifies the task's current instruction pointer (`RIP`/`PC`) and uses `PTRACE_POKEDATA` to temporarily inject a small bootstrap payload. This payload is typically designed to execute a system call (such as `mmap` or `memfd_create`) to allocate a dedicated memory region for the full parasite blob.
### 3. Memory Exchange Optimization
To maximize efficiency and avoid thousands of slow `ptrace` calls, CRIU uses a **memory exchange** technique:
* The parasite's memory region is often backed by a file descriptor (e.g., `memfd`).
* CRIU maps this same file descriptor into its own address space.
* This allows the CRIU coordinator to write the parasite code, Global Offset Table (GOT), and arguments directly into the target's memory at local memory speeds.
### 4. Relocation and GOT Patching
Since the parasite is a Position-Independent Executable (PIE), CRIU must patch its GOT table with the actual addresses where the blob was mapped in the target process's address space.
### 5. Starting the Daemon
CRIU sets the task's instruction pointer to the entry point of the parasite and resumes execution using `PTRACE_CONT`. The parasite initializes its own stack, sets up signal handling for its own internal use, and enters **daemon mode**.
## Execution and Communication
The parasite runs as a daemon within the target task's context, communicating with the main CRIU process via a Unix domain socket.
### Control Loop
The parasite enters a loop where it waits for commands from the CRIU coordinator. Each command follows a **Request-Response** pattern:
1. **Request**: CRIU sends a command ID (e.g., `PARASITE_CMD_DUMP_PAGES`) and any necessary arguments through the socket.
2. **Execution**: The parasite executes the requested action within the task's context (e.g., calling `vmsplice` on its own memory).
3. **Response**: The parasite sends an acknowledgment (ACK) and optional data back to CRIU.
### Supported Actions
* **Memory Dumping**: Efficiently transfers memory pages to CRIU using the `vmsplice()` system call.
* **Credential Extraction**: Captures UIDs, GIDs, and capability sets.
* **Timer and Signal State**: Reads interval timers and signal action tables that are not visible through `/proc`.
* **Thread Coordination**: In multi-threaded processes, the parasite coordinates state collection across all threads.
## Cleanup and Cure
Once the state capture is complete, CRIU performs a "cure" operation to return the process to its original state:
1. CRIU sends the `PARASITE_CMD_FINI` command to the daemon.
2. The parasite unmaps its allocated memory and prepares to exit.
3. CRIU restores the original register state (including the instruction pointer) and the original code bytes that were overwritten during the bootstrap phase.
4. CRIU detaches from the task, allowing it to resume normal operation or terminating it as requested.
In Linux, a signal is marked as **pending** if it has been delivered to a task but has not yet been handled (e.g., because the signal is blocked or the task is currently stopped). CRIU provides full support for capturing and restoring these pending signal queues, ensuring that the application's signal state remains perfectly consistent across a checkpoint.
## Checkpoint and Restore of Pending Signals
CRIU manages pending signals using specialized `ptrace` interfaces and signal injection system calls.
### 1. Checkpointing (Dumping)
During a dump, CRIU must extract both the list of pending signals and the detailed metadata associated with each one (the `siginfo_t` structure).
* **PTRACE_PEEKSIGINFO**: CRIU uses this system call (introduced in Linux kernel v3.10 specifically to support CRIU) to read the signal queues of the target task without actually delivering them.
* **Private Signals**: Signals delivered to a specific thread are read using standard peeking.
* **Shared Signals**: Signals delivered to the entire process (which can be handled by any thread) are read by adding the `PTRACE_PEEKSIGINFO_SHARED` flag.
* **Batch Processing**: CRIU reads signals in batches (typically 32 at a time) to efficiently capture entire queues, which is common in high-throughput applications.
* **Signal Mask**: In addition to the pending signals, CRIU uses `PTRACE_GETSIGMASK` to capture the set of signals currently blocked by each thread. This mask is essential because it determines why the signals were pending in the first place.
### 2. Restoration
To recreate the pending state, CRIU re-injects the captured signals into the newly created process tree before it begins normal execution.
* **rt_sigqueueinfo()**: For process-wide (shared) signals, CRIU uses this system call to send a signal to a process with the original `siginfo_t` data.
* **rt_tgsigqueueinfo()**: For thread-specific (private) signals, CRIU uses this variant to target a specific thread ID (TID) within a process.
* **Preserving siginfo**: These system calls allow CRIU to pass the exact original `siginfo_t` structure (including the sender's PID, UID, and any signal-specific data), ensuring the restored task sees the identical signal context.
## Shared vs. Private Pending Signals
* **Multi-threaded Handling**: In multi-threaded applications, signals are carefully tracked:
* **Shared signals** are stored in the process leader's `core.img`.
* **Private signals** are stored in the `core.img` corresponding to each individual thread.
* **Restore Order**: Signals are restored while the task is still under CRIU's control, ensuring that they remain pending until the task is finally resumed and its original signal mask is applied.
A critical requirement for successful checkpoint/restore is ensuring that each process and thread is restored with its original **Process ID (PID)** and **Thread ID (TID)**. Applications frequently rely on these IDs for inter-process communication, signal delivery, and as keys for shared resources (such as System V IPC).
## Restoration Mechanisms
CRIU employs two primary methods to request specific PIDs from the Linux kernel during restoration.
### 1. The Legacy Interface: `ns_last_pid`
On older kernels, Linux does not provide a direct way to request a specific PID during a `fork()` or `clone()` call. Instead, CRIU uses the `/proc/sys/kernel/ns_last_pid` interface:
1. CRIU acquires a global lock (`lock_last_pid`) to minimize the chance of other processes interfering.
2. It writes `N-1` to `/proc/sys/kernel/ns_last_pid`.
3. It calls `fork()`.
4. The kernel assigns the next available PID, which should be `N`.
**Limitations**:
* **Race Conditions**: Other processes on the system (outside of CRIU's control) might fork and "steal" the intended PID between the write and the fork.
* **Performance**: Repeatedly writing to the `/proc` filesystem and calling `fork()` is slow, especially for large process trees.
* **Nesting Complexity**: Handling nested PID namespaces with this interface requires recursively entering namespaces and managing the legacy interface at each level.
### 2. The Modern Interface: `clone3()` with `set_tid`
Introduced in Linux kernel v5.5, the `clone3()` system call provides a much more robust and efficient mechanism via the `set_tid` array in the `clone_args` structure.
* **Atomic Assignment**: CRIU explicitly specifies the desired PID directly during the creation call.
* **No Races**: The PID assignment is atomic with process creation, eliminating the risk of PID theft.
* **Efficiency**: Offers significant performance improvements, particularly during the restoration of large, multi-threaded applications.
* **Full Hierarchy Support**: CRIU can pass an array of PIDs to `set_tid`, allowing it to simultaneously set the process's identity in all nested PID namespaces.
## Implementation in CRIU
CRIU includes architecture-specific assembly wrappers (`RUN_CLONE3_RESTORE_FN`) to safely execute these calls during the critical restoration phase.
* **Automatic Selection**: CRIU automatically detects the presence of `clone3()` and `set_tid` support during the [Kerndat](kerndat.md) phase. If the modern interface is available, it is prioritized.
* **Thread Restoration**: Individual threads are restored using the same mechanisms, ensuring that their TIDs match the original state.
The **Pidfd Store** is an internal CRIU mechanism used during iterative migration to reliably identify processes across multiple pre-dump iterations. It leverages the Linux kernel's `pidfd` interface to eliminate the risks associated with PID reuse.
## The Problem: PID Reuse
In an iterative migration workflow, CRIU performs multiple `pre-dump` operations. Each iteration captures memory pages that have changed since the previous snapshot. To do this safely, CRIU must ensure that it is still talking to the *exact same process* it was in the previous iteration.
If a process dies between iterations and the kernel assigns its old PID to a new, unrelated process, a naive check based only on the PID would fail to detect this change. Performing an incremental dump on a new process using the state of an old one would lead to corrupted images and a failed restoration.
## How the Pidfd Store Works
The Pidfd Store allows CRIU to maintain a persistent, race-free handle for every process in the tree.
### 1. Capturing Pidfds
During the first pre-dump, CRIU calls `pidfd_open()` for every task it captures. Unlike a numeric PID, a **pidfd** is a file descriptor that refers to a specific process *instance*. If that process terminates, its pidfd becomes invalid and will never refer to a subsequent process, even if the numeric PID is reused.
### 2. Persistent Storage via "The Socket Trick"
CRIU often operates as a service, receiving commands via RPC. To keep pidfds alive between independent RPC calls, CRIU uses a clever "socket trick":
* CRIU creates a Unix domain socket and connects it to itself.
* It "sends" the captured pidfds into this socket using the `SCM_RIGHTS` mechanism.
* The Linux kernel stores these file descriptors in the socket's internal buffer. Because the socket is connected to itself, the descriptors remain queued in the kernel until CRIU explicitly reads them back.
### 3. Identity Verification
In each subsequent `pre-dump` or the final `dump` command:
1. CRIU "drains" the pidfds from its internal storage socket.
2. It builds a hash table mapping PIDs to these stable pidfd handles.
3. Before capturing state for a PID, CRIU verifies the task against the stored pidfd.
4. If the pidfd is still valid, CRIU knows it is the same process and can safely perform an incremental memory dump.
5. If the pidfd is invalid or missing, CRIU detects a **PID reuse** event and treats the process as entirely new, performing a full dump to maintain consistency.
## Kernel Requirements
The Pidfd Store requires modern kernel features (automatically detected via [Kerndat](kerndat.md)):
* `pidfd_open()` (Kernel v5.3+)
* `pidfd_getfd()` (Kernel v5.6+, used to transfer the storage socket between service components).
A **pidfd** is a file descriptor that refers to a specific process. Unlike traditional numeric PIDs, which can be reused by the kernel once a process terminates, a pidfd is a stable and race-free handle. It remains valid as long as the descriptor is open, even after the process it refers to has died. CRIU provides full support for checkpointing and restoring pidfds owned by applications.
## How CRIU Handles Pidfds
CRIU treats pidfds as a specialized type of file descriptor. During a dump, it captures both the target of the pidfd and its configuration.
### 1. Checkpointing (Dumping)
When CRIU encounters a pidfd in a process's file descriptor table:
* **Target Identification**: It parses `/proc/$pid/fdinfo/$fd` to determine the numeric PID that the pidfd currently refers to.
* **Tree Validation**: CRIU verifies that this target PID is part of the process tree being checkpointed. This ensures that the process will be available for re-binding during restoration.
* **Metadata Capture**: CRIU records the target process's namespace-local PID and any flags associated with the pidfd (such as `O_NONBLOCK` or `O_CLOEXEC`).
### 2. Restoration
Restoring a pidfd involves recreating a handle that points to the equivalent process in the newly restored tree.
* **Alive Processes**: If the target process is alive, CRIU simply calls the `pidfd_open()` system call on the restored PID of that task.
* **Dead Processes**: A unique feature of pidfds is that they can be held open even after the target process has exited. To restore this state, CRIU:
1. Creates a temporary "helper" process.
2. Opens a pidfd to this helper.
3. Terminates the helper process.
This leaves the restored application with a valid pidfd that refers to a dead process, perfectly mimicking the original state.
## Kernel Evolution: From Anonymous Inodes to `pidfs`
The underlying implementation of pidfds in the Linux kernel has changed over time:
* **Pre-v6.9**: Pidfds were implemented using anonymous inodes. In `/proc/$pid/fd`, they appeared as `anon_inode:[pidfd]`.
* **v6.9 and later**: Pidfds are now part of a dedicated **pidfs** filesystem. They appear in `/proc` as `pidfd:[N]`.
CRIU automatically detects these kernel differences and handles both formats transparently, ensuring that pidfds are correctly identified and restored regardless of the host kernel version.
## Current Limitations
* **PIDFD_THREAD**: Support for pidfds that target specific threads (created with the `PIDFD_THREAD` flag) is currently not implemented.
## See also
* [Pidfd Store (Iterative Migration)](pidfd-store.md)
Restartable Sequences (rseq) is a Linux kernel feature (introduced in v4.18) that enables high-performance userspace operations on per-CPU data without requiring atomic instructions or traditional locking. Each thread registers a `struct rseq`, and the kernel ensures that if a thread is preempted or interrupted while inside a critical section, it is "restarted" by jumping to a predefined abort handler.
## The Challenge of C/R with rseq
Checkpointing and restoring rseq is exceptionally delicate because the kernel's rseq state is tightly coupled with process execution.
1. **Dumping Sensitivity**: If an infected thread is allowed to run even briefly (e.g., to execute parasite code), the kernel's `rseq_handle_notify_resume` hook may be triggered. This would cause the kernel to "fix up" the rseq state, clearing critical section pointers in userspace memory and losing the very state CRIU needs to capture.
2. **Restoration Morphing**: During restoration, CRIU "morphs" into the target process. If the CRIU binary itself was compiled with rseq support (common in modern distributions), it may have an active rseq registration that must be carefully managed before the memory layout is swapped.
## How CRIU Handles rseq
CRIU provides robust support for rseq, ensuring that threads interrupted within a critical section correctly restart after restoration.
### 1. Checkpointing (Dumping)
CRIU captures the rseq configuration without disturbing the thread's execution state:
* **PTRACE_GET_RSEQ_CONF**: CRIU uses this ptrace command (Kernel v5.13+) to retrieve the address, size, and signature of the `struct rseq` registered for each thread.
* **External Peeking**: To avoid triggering kernel fixups, CRIU **does not** use its standard parasite code to read rseq-related memory. Instead, it uses `PTRACE_PEEKDATA` to read the `struct rseq` and `struct rseq_cs` (critical section descriptor) directly from the outside while the task is frozen.
* **Critical Section Detection**: By reading the `rseq_cs` pointer within the `struct rseq`, CRIU identifies if a thread was in the middle of a sequence at the time of the snapshot.
### 2. Restoration
The restoration process involves two critical rseq-related steps:
* **Unregistering Restorer rseq**: Before CRIU performs the final "morphing" (unmapping its own memory and mapping the application's memory), it must explicitly **unregister** any rseq area used by the CRIU process itself. Failing to do so would cause the kernel to attempt to update a `cpu_id` field in memory that has been unmapped, resulting in an immediate segmentation fault.
* **Re-establishing Application rseq**: Once the application's memory layout and thread registers are restored, CRIU calls the `rseq()` system call for each thread. It re-registers the original `struct rseq` at its original address.
* **Automatic Restart**: Because the `rseq_cs` pointer is restored as part of the thread's memory, the kernel will detect the active critical section upon the first resumption and automatically trigger the application's restart/abort logic, ensuring data integrity.
## Kernel Requirements
* **rseq support**: Linux Kernel v4.18+
* **PTRACE_GET_RSEQ_CONF**: Linux Kernel v5.13+ (Required for reliable automated detection).
The **Restorer Context** refers to the final stage of the restoration process, where a CRIU process "morphs" itself into the target application. This critical transition is performed by a specialized [PIE](code-blobs.md) blob known as the **Restorer PIE**.
## Why a Dedicated Context is Necessary
During the final stage of restoration, CRIU must accomplish two conflicting goals:
1. **Memory Swapping**: It must unmap all of CRIU's own code, stack, and data to completely clear the address space for the application.
2. **Memory Re-mapping**: It must map the application's original memory regions (VMAs) back into their exact original addresses.
While these operations are occurring, some code must remain in the address space to execute the necessary `munmap()` and `mmap()` system calls. The Restorer PIE is designed to reside in a temporary "safe hole" in the address space—a range that does not conflict with either CRIU's temporary mappings or the application's final layout.
## The Restoration Workflow
1. **Preparation**: The root CRIU process identifies the restorer code and prepares it for distribution.
2. **Forking**: The process tree is recreated. Since the restorer code is mapped in the root task before forking, all child processes share the same physical memory for the restorer via standard Copy-on-Write (COW).
3. **Safe Hole Detection**: Each restored process scans its target memory layout (from the `mm.img` file) to find a contiguous area large enough to hold the restorer code and its stack.
4. **Remapping**: Each process uses `mremap()` to move the shared restorer blob to its specific safe hole.
5. **Execution Jump**: The process jumps from the main CRIU code into the restorer PIE.
6. **Cleanup and Reconstruction**: The restorer PIE unmaps CRIU, recreates the application's original mappings, and populates them with data from the image files.
7. **Final Transition (Sigreturn)**: The very last step is calling `sigreturn()`. The restorer prepares a special signal frame on the stack containing the application's original register state (including the instruction pointer). The kernel then loads this state, effectively resuming the application from the exact point of the checkpoint.
## Technical Characteristics
### Freestanding PIE
Because the restorer runs in an environment where standard libraries have been unmapped, it is a **freestanding** Position-Independent Executable. It contains its own minimal assembly-level system call wrappers and does not depend on `glibc` or any external runtime.
### Conflict Avoidance
The algorithm for finding the "safe hole" is architecture-specific. It must account for various kernel-mapped regions like the vDSO, the stack, and potential guard pages to ensure that the restorer code never overlaps with memory that the application needs.
During dump and restore operations, CRIU requires numerous internal file descriptors (FDs) to manage logs, images, RPC communication, and transport sockets. Because the application being checkpointed or restored may use any arbitrary FD number, CRIU must ensure its internal descriptors never conflict with those of the application. To achieve this, CRIU uses the **Service FD Engine**.
## The Protected Range
CRIU avoids FD collisions by placing its internal descriptors in a "protected" range at the very top of the process's file descriptor table.
* **Lifting Limits**: Upon startup, CRIU attempts to lift its `RLIMIT_NOFILE` resource limit (using `rlimit_unlimit_nofile()`) to a very high value (typically 1,048,576 or higher).
* **Top-Down Allocation**: Service FDs are allocated starting from the maximum allowed FD number and working downwards. This strategy places them as far as possible from the range typically used by applications (which usually start from 0 and work upwards).
## Service FD Engine Mechanisms
The engine (`criu/servicefd.c`) provides a robust abstraction for managing these descriptors through several key techniques:
### 1. Per-Process Isolation in Shared Tables
In scenarios where multiple processes share the same file descriptor table (e.g., threads or processes created with `CLONE_FILES`), CRIU assigns a unique `service_fd_id` to each task. The engine uses this ID to offset the service FD range, ensuring that even tasks sharing an FD table have distinct, non-overlapping slots for their internal CRIU descriptors.
### 2. Descriptor Relocation
When CRIU opens a file for its own use (such as an image file or the log), the kernel initially assigns it the lowest available FD number (e.g., FD 3). CRIU then uses `fcntl(F_DUPFD_CLOEXEC)` or `dup3()` to "move" that descriptor to its designated high-range slot and immediately closes the original low-numbered descriptor.
### 3. Protection Flags and Safety
During critical phases of restoration—specifically when the application's FDs are being "planted" into their final numeric slots—CRIU sets a global `sfds_protected` flag. While this flag is set, the service FD engine is "locked." Any attempt by the code to modify or close a service descriptor will trigger an immediate safety crash (BUG), preventing accidental corruption of the restoration state.
## Common Service FD Types
The engine manages various types of descriptors, each with a specific role:
* **LOG_FD**: The descriptor for the main CRIU log file.
* **IMG_FD**: The descriptor used for accessing image files.
* **RPC_SK**: The socket used for RPC communication with external management tools.
* **TRANSPORT_FD**: Sockets used to "send" and "receive" FDs between processes via `SCM_RIGHTS`.
* **PROC_FD**: A stable handle to the `/proc` filesystem.
* **CGROUP_YARD**: A descriptor for the temporary directory used during cgroup restoration.
CRIU provides comprehensive support for capturing and reconstructing the various ways processes share memory in Linux. This includes anonymous shared regions, file-backed shared mappings, and System V IPC segments.
## Types of Shared Memory
CRIU categorizes shared memory into three primary types, each with a dedicated restoration strategy:
### 1. Shared Anonymous Mappings
Created via `mmap(..., MAP_SHARED | MAP_ANONYMOUS, ...)`, these regions have no persistent backing file on disk but are shared between a parent and its children after a `fork()`, or between unrelated processes that inherit the mapping.
* **Identification**: CRIU identifies these regions by parsing `/proc/$pid/maps`. For shared anonymous regions, the kernel assigns a unique **internal inode number** (often appearing in the `inode` column of maps). CRIU uses this inode number as a `shmid` to group and identify identical mappings across the entire process tree.
* **Restoration via memfd**: During restoration, CRIU uses the `memfd_create()` system call to create an anonymous, RAM-backed file.
* One process (the designated "master" for that specific `shmid`) creates the `memfd`, populates it with the memory contents captured in `pages-shmem.img`, and maps it.
* All other processes that shared the original region map the same `memfd` file descriptor, ensuring that any subsequent writes are visible to all participants, just as they were before the checkpoint.
### 2. Shared File Mappings
Created via `mmap(..., MAP_SHARED, fd, ...)`, these regions are backed by a regular file on the filesystem.
* **Mechanism**: CRIU records the file's unique identity (device and inode), the offset within the file, and the mapping length.
* **Restoration**: Each process re-opens the original file (or a restored version of it) and calls `mmap()` with the `MAP_SHARED` flag. The Linux kernel's standard page cache mechanism automatically handles the sharing and synchronization between processes.
### 3. System V IPC Shared Memory
Managed via the legacy `shmget()` and `shmat()` APIs, these segments are part of the kernel's IPC subsystem.
* **Mechanism**: CRIU captures the segment's metadata (key, ID, permissions, size) and its full data contents during the dump.
* **Restoration**: CRIU recreates the IPC segments using `shmget()` with the original parameters and repopulates the data. The restored processes then attach to these segments using `shmat()`, ensuring that IPC-based communication continues seamlessly.
## Advanced Coordination Features
CRIU leverages modern kernel features to handle complex sharing accurately:
* **kcmp**: Used to definitively verify if two memory mappings in different processes refer to the same underlying kernel object (via `KCMP_VM`), ensuring that shared resources are only dumped once.
* **Futex Synchronization**: During restoration, CRIU uses futexes to coordinate between the "master" process (which populates shared memory) and "slave" processes, ensuring that no process starts execution until the shared memory state is fully consistent.
CRIU provides extensive support for checkpointing and restoring a wide variety of Linux network sockets, including Unix domain sockets, IPv4/IPv6 (TCP, UDP, RAW), Netlink, and Packet sockets.
## Key Information Captured
To faithfully restore a socket, CRIU must capture its full kernel state:
1. **Identity**: Family (AF_INET, AF_UNIX, etc.), type (SOCK_STREAM, SOCK_DGRAM), and protocol (TCP, UDP, etc.).
2. **Addresses**: Local binding addresses and, for connected sockets, the remote peer address and port.
3. **Socket Options**: A wide range of options (e.g., `SO_KEEPALIVE`, `SO_REUSEADDR`, `TCP_NODELAY`, buffer sizes) are captured and reapplied.
4. **Queues**: Data currently residing in the send and receive buffers is extracted and re-injected upon restoration.
5. **State**: Whether the socket is listening, connected, or in a transitional state (like `FIN_WAIT` or `CLOSE_WAIT` for TCP).
## The Dumping Process
CRIU combines information from multiple sources to build a complete picture of each socket.
### 1. sock_diag
The primary source of truth is the **sock_diag** kernel module. CRIU sends Netlink requests to `sock_diag` to retrieve detailed internal state for most socket families. This provides protocol-level information that is not available via standard userspace APIs.
### 2. SCM_RIGHTS and Parasite
For deeper inspection—such as peeking at socket queues or enabling TCP repair mode—CRIU uses its **parasite code** to send the actual socket file descriptor to the CRIU process via a Unix domain socket using the `SCM_RIGHTS` mechanism. This allows the CRIU coordinator to perform `ioctl`, `getsockopt`, and `recv(MSG_PEEK)` calls directly on a local copy of the socket.
## Restoration Strategies
### TCP Repair Mode
Restoring a TCP connection without disrupting the peer (and without sending any packets) is a major challenge. CRIU uses a specialized kernel feature called **TCP Repair Mode**:
1. CRIU creates a new socket and immediately puts it into repair mode.
2. While in this mode, CRIU can manually set the sequence numbers, window sizes, and other protocol-level state to match the captured dump.
3. It populates the send and receive queues with the dumped data.
4. Finally, it takes the socket out of repair mode, allowing the connection to resume as if it were never interrupted.
### Unix Sockets and SCM_RIGHTS
Unix sockets are unique because they can be used to transfer other file descriptors. CRIU captures these "in-flight" descriptors (files that have been sent but not yet received) and ensures they are correctly re-queued for the restored process.
## Supported Socket Families
* **AF_UNIX**: Full support for Stream, Datagram, and Sequential Packet types, including abstract and file-backed names.
* **AF_INET / AF_INET6**:
* **TCP**: Full connection state restoration via Repair Mode.
* **UDP / UDPLITE**: Captures addresses, options, and queues.
* **RAW**: Captures protocol settings and binding state.
* **AF_NETLINK**: Captures the state of Netlink sockets used for kernel communication (e.g., for routing or audit).
* **AF_PACKET**: Supports capturing packet filters (BPF) and specific interface bindings.
Restoring a complex process tree is a multi-step operation coordinated by a central CRIU process and executed across the newly created process tree. Each stage is synchronized to ensure that dependencies (such as shared files and parent-child relationships) are met and security invariants are maintained.
## The Synchronization Mechanism
CRIU uses a global state machine (defined as `CR_STATE_*` constants) to coordinate between the main CRIU process and the tasks being restored. Tasks use **futexes** in shared memory to signal the completion of their work in each stage and wait for the coordinator to signal the transition to the next stage.
The main CRIU process performs initial image analysis, resolves shared resources, and prepares the restorer code blobs. It then forks the **root task** of the tree being restored. The root task performs initial pre-checks and begins its environmental setup.
The root task (and specialized helpers) initializes the required namespaces (Mount, Network, IPC, UTS, Time). This ensures that all subsequent processes in the tree are created within the correct containerized environment from the moment of their birth.
## Stage 3: Process Tree Forking (`CR_STATE_FORKING`)
The process tree is recursively forked until all processes are recreated.
* **PID Restoration**: Processes are created with their original PIDs using the `clone3()` system call or the `ns_last_pid` interface.
* **Transport Setup**: Each task creates an abstract Unix domain socket to "receive" shared file descriptors from its designated "master" peers.
## Stage 4: Main Resource Restoration (`CR_STATE_RESTORE`)
This is the primary stage where the bulk of the application state is reconstructed:
* **Files and Sockets**: File descriptors are opened locally or received via `SCM_RIGHTS`.
* **Memory Mapping**: VMAs are recreated via `mmap()`.
* **Restorer Jump**: Each task "morphs" by jumping from the main CRIU code into the freestanding **Restorer PIE** blob.
* **Threads**: Individual application threads are recreated within each process.
## Stage 5: Signal Synchronization (`CR_STATE_RESTORE_SIGCHLD`)
Tasks restore their original `SIGCHLD` handlers. This stage serves as a critical synchronization point to transition from CRIU's internal error-tracking (which relies on `SIGCHLD` to detect failed restoration steps in children) to the application's original signal handling logic.
## Stage 6: Security and Credentials (`CR_STATE_RESTORE_CREDS`)
For security reasons, this is the final stage before the application resumes execution. CRIU ensures that sensitive attributes are restored in a specific order:
1. **Credentials**: UIDs, GIDs, and Capability sets are applied.
2. **Seccomp**: Security filters are enabled only after the final credentials are in place.
3. **Process Attributes**: The "dumpable" status and parent-death signals (`pdeath_sig`) are re-established.
By delaying these steps until the very end, CRIU prevents potential security vulnerabilities where a partially-restored process could be intercepted or manipulated while in a transitional state.
## Stage 7: Resumption (`CR_STATE_COMPLETE`)
The tasks execute their final `sigreturn()` call from within the Restorer PIE. This restores the original register state (including the instruction pointer) and jumps the CPU back into the application's code. The process tree is now fully restored and running.
Checkpointing and restoring established TCP connections is one of CRIU's most advanced features. It allows migrating live applications without dropping active network sessions, provided that the network infrastructure (such as IP routing, virtual IPs, or NAT) supports the transition.
## The Challenge
Standard TCP is managed entirely by the kernel's network stack. Under normal circumstances, userspace cannot:
1. Read or set internal sequence numbers.
2. Directly populate the kernel's send and receive buffers.
3. Transition a socket between states (e.g., from `SYN_SENT` to `ESTABLISHED`) without performing an actual network handshake.
Attempting to restore a connection without specific kernel support would lead to immediate sequence number mismatches and connection resets (RST) from the remote peer.
## The Solution: TCP Repair Mode
To address these limitations, CRIU developers implemented **TCP Repair Mode** in the Linux kernel. When a socket is placed into repair mode, the TCP state machine is suspended, and the kernel allows userspace to manipulate its internal parameters directly.
### Checkpointing (Dumping)
1. **Network Locking**: Before capturing the socket state, CRIU "locks" the connection using **iptables** or **nftables**. This ensures the kernel drops any incoming packets from the peer, preventing the connection state from changing while CRIU is performing the dump.
2. **Enable Repair**: CRIU puts the socket into repair mode (`TCP_REPAIR`).
3. **State Capture**: Using the `libsoccr` library, CRIU extracts:
* **Sequence Numbers**: The current positions in the data stream (`TCP_QUEUE_SEQ`).
* **Window Parameters**: Send and receive window sizes and offsets (`TCP_REPAIR_WINDOW`).
* **Queue Data**: The actual bytes currently residing in the kernel's send and receive buffers.
4. **Silent Close**: Once the state is captured, the socket is closed while still in repair mode. This is crucial as it prevents the kernel from sending `FIN` or `RST` packets to the peer, keeping the connection "alive" from the peer's perspective.
### Restoration
1. **Socket Creation**: CRIU creates a new socket and immediately enables repair mode.
2. **Binding**: The socket is bound to the original local IP address and port.
3. **State Injection**: captured parameters (sequences, windows, options) are applied to the new socket using `setsockopt`.
4. **Queue Re-population**: The send and receive buffers are re-filled with the original data.
5. **Activation**: CRIU takes the socket out of repair mode. The kernel now considers the connection to be in the exact state it was at the moment of the checkpoint.
6. **Network Unlocking**: Finally, the network locks are removed. The application resumes, and the next packet sent or received will have perfectly consistent sequence numbers.
## Network Locking Methods
CRIU supports multiple strategies to manage the network during migration:
* **nftables** (Preferred): Uses the modern `nft` API to create efficient, temporary rules.
* **iptables**: Uses traditional `iptables` commands to drop packets for the specific 4-tuple.
* **Skip**: Allows external orchestration (e.g., by an SDN controller) to handle packet buffering and redirection.
CRIU relies on a wide array of advanced Linux kernel features and userspace libraries to perform transparent checkpoint and restore.
## Kernel Technologies
### Core C/R Capabilities
* **kcmp()**: A system call used to identify shared resources (files, memory mappings, namespaces) between processes by performing internal kernel pointer comparisons.
* **clone3()**: A modern process creation interface that allows CRIU to atomically request specific PIDs and TIDs, even across nested PID namespaces.
* **prctl() Extensions**:
* `PR_SET_MM`: Allows the restorer to reconstruct a process's original memory layout (code, data, heap, etc.).
* `PR_GET_TID_ADDRESS`: Captures the address used for `set_tid_address`.
* `PR_SET_THP_DISABLE`: Preserves the status of Transparent Huge Pages.
* `/proc/$pid/map_files`: Provides stable handles to files mapped into a process's memory.
* `/proc/$pid/fdinfo`: Exposes internal state for file descriptors, including positions, flags, and socket handles.
* `ioctl(PAGEMAP_SCAN)`: Efficiently identifies dirty and present pages in large address spaces.
* **sock_diag**: A netlink-based interface used to retrieve detailed protocol-level state for sockets (TCP, UDP, Unix, etc.).
### Advanced Subsystems
* **TCP Repair Mode**: A specialized socket state that allows CRIU to capture and restore the full internal state of TCP connections without sending network packets.
* **Userfaultfd**: Enables **Lazy Migration** by allowing CRIU to handle page faults in userspace and load memory pages on-demand.
* **Mount V2 APIs**: Uses `fsopen()`, `fsmount()`, `open_tree()`, and `move_mount()` to robustly reconstruct complex filesystem hierarchies and propagation groups.
* **Netfilter (nftables/iptables)**: Used to "lock" network connections during migration to prevent state changes.
## Userspace Technologies
### Compel
[Compel](../compel.md) is a dedicated sub-project that provides the infrastructure for **Parasite Injection**. It allows CRIU to execute self-contained code (PIE) within the context of a target process to capture internal state.
### Google Protocol Buffers (protobuf)
CRIU uses [Protocol Buffers](https://developers.google.com/protocol-buffers/) as the standard serialization format for all image files. This ensures a structured, extensible, and cross-version compatible way to store process state.
### ZDTM (Zero-Downtime Migration)
[ZDTM](zdtm-test-suite.md) is CRIU's comprehensive test suite. It includes hundreds of tests that verify the functional correctness of C/R across various architectures and kernel versions.
CRIU provides support for checkpointing and restoring various types of Linux terminals (TTYs), with a primary focus on **Unix98 Pseudoterminals (PTYs)**.
## Key Information Captured
For each TTY instance, CRIU captures a comprehensive set of kernel metadata:
1. **Identity**: The TTY type (PTY, Console, Serial, or Virtual Terminal), subtype (Master or Slave), and its unique kernel index.
2. **Configuration**: Detailed `termios` settings (baud rate, parity, control characters) and window size parameters (`winsize`).
3. **Ownership and Permissions**: The original UID/GID and mode of the TTY device node.
4. **Process Context**: Controlling terminal status, Session ID (SID), and Foreground Process Group (PGRP).
5. **Extended State**: Lock status (`TIOCGLCKTRMIOS`), exclusive mode settings, and packet mode (`TIOCPKT`) flags.
## The PTY Index Challenge
A major challenge in restoring PTYs is that the Linux kernel assigns indices (e.g., the `N` in `/dev/pts/N`) sequentially when `/dev/ptmx` is opened. Standard userspace APIs do not allow requesting a specific index.
### The "Sequential Opening" Strategy
To ensure each PTY is restored with its original index, CRIU employs a specialized "brute-force" technique:
1. **Looping Open**: CRIU enters a loop, repeatedly calling `open("/dev/ptmx")`.
2. **Index Verification**: After each open, it queries the assigned index using the `TIOCGPTN` ioctl.
3. **Consuming Indices**: If the assigned index is lower than the target index, CRIU **keeps the file descriptor open**. This prevents the kernel from reassigning that index.
4. **Target Match**: Once the kernel assigns the correct original index, CRIU uses that descriptor as the restored master PTY.
5. **Cleanup**: All "placeholder" descriptors opened during the loop are then closed, freeing those indices for the rest of the system.
## Restoration Workflow
1. **Master Peer Reconstruction**: A designated process recreates the master PTY using the sequential opening strategy.
2. **Slave Peer Attachment**: Slave processes open the corresponding `/dev/pts/N` devices. Because the master was created with the correct index, these slaves automatically link to the correct peer.
3. **State Application**: Termios, window sizes, and device ownership are applied to the newly opened descriptors.
4. **Controlling Terminal Re-binding**: CRIU re-establishes the relationship between each process and its controlling terminal using the `TIOCSCTTY` ioctl.
## Current Limitations
* **Buffered Data**: Captured TTY input and output queues (data that was sent but not yet read) are currently not fully restored. CRIU ensures the *interface* is restored, but the application may see a reset of buffered streams.
* **Legacy BSD PTYs**: Support for older BSD-style PTYs is not implemented, as the modern Linux kernel does not provide the necessary introspection to reliably pair these devices.
CRIU supports checkpointing and restoring Linux TUN/TAP virtual network interfaces. These devices are frequently used in VPN clients, virtualization platforms (like QEMU), and container networking.
## How CRIU Handles TUN/TAP
CRIU manages TUN/TAP as a combination of a **Network Interface** (the link visible to the kernel) and a **File Descriptor** (the handle used by the application to send and receive packets).
### 1. Checkpointing (Dumping)
During a dump, CRIU identifies TUN/TAP descriptors and collects their full kernel state:
* **Device Attributes**: The interface name, type (TUN for L3 or TAP for L2), and operational flags (e.g., `IFF_NO_PI`, `IFF_VNET_HDR`).
* **Persistency**: Whether the device is persistent (`IFF_PERSIST`), meaning it survives even when no process has it open.
* **Buffer Sizes**: Captures the send buffer size (`TUNGETSNDBUF`) and the virtual network header size (`TUNGETVNETHDRSZ`).
* **Multi-Queue State**: CRIU identifies if multiple file descriptors are attached to different queues of the same TUN/TAP device, allowing for parallel I/O.
* **Ownership**: Captures the UID and GID associated with the TUN/TAP device.
### 2. Restoration
To recreate the TUN/TAP environment exactly as it was, CRIU performs the following:
* **Interface Creation**: Recreates the virtual link or attaches to an existing persistent one using `TUNSETIFF`.
* **Index Preservation**: Uses the `TUNSETIFINDEX` ioctl to ensure the restored interface has the exact same numeric index as the original. This is critical for applications that have cached the interface index.
* **Queue Re-attachment**: For multi-queue devices, CRIU uses `TUNSETIFF` in combination with `TUNSETQUEUE` to correctly re-link each restored file descriptor to its original queue.
* **State Application**: Restores the original buffer sizes, ownership, and persistent status. If a device was not originally persistent, CRIU explicitly drops the persistency after the application has attached to it.
## Current Limitations
* **Packet Filters (BPF)**: Capturing a TAP interface with a complex BPF filter attached is currently **not supported**. The kernel does not provide a robust way to extract the filter program and re-attach it during restoration without the original application context.
* **In-flight Packets**: Data currently residing in the kernel's internal TUN/TAP queues (packets sent by the application but not yet processed by the virtual device, or vice versa) is not preserved across a checkpoint.
CRIU supports checkpointing and restoring Unix domain sockets (AF_UNIX), including Stream, Datagram, and Sequential Packet types. Unix sockets are unique because they can be bound to paths in the filesystem and are frequently used to transfer file descriptors between processes.
## Key Challenges
1. **Path and Inode Decoupling**: A Unix socket's address (its bind path) and the actual socket file on disk are not intrinsically linked in the kernel. If a socket file is moved or unlinked after `bind()`, the socket still reports its original address.
2. **In-flight Descriptors**: Unix sockets can contain "in-flight" file descriptors sent via `SCM_RIGHTS` that have been sent by one process but not yet received by the peer.
3. **Cross-Namespace Bindings**: Sockets in one mount namespace may be bound to paths that are only visible or reachable from another mount namespace.
## CRIU's Solution: `SIOCUNIXFILE`
To reliably restore Unix sockets, CRIU developers upstreamed the `SIOCUNIXFILE` ioctl to the Linux kernel. This ioctl allows CRIU to:
* Retrieve an `O_PATH` file descriptor to the actual socket file on disk, regardless of its current name or overmounting status in the filesystem.
* By obtaining this `O_PATH` descriptor, CRIU can definitively identify the exact mount point and inode of the socket file, ensuring it can be recreated in the correct location during restoration.
## Dumping Workflow
1. **Identity and State**: CRIU uses the `sock_diag` netlink interface to retrieve the socket's type, state, and peer ID.
2. **Peer Linking**: For connected or related sockets (like those created via `socketpair()`), CRIU uses the peer information to link them together in the process tree model.
3. **File Handle Retrieval**: For sockets bound to the filesystem, CRIU uses `SIOCUNIXFILE` to get a handle to the socket file and records its location.
4. **Queue and FD Capture**: Send and receive queues are peeked to capture pending data. Crucially, any file descriptors currently residing in the socket's queues are also captured and dumped.
## Restoration Workflow
1. **Socket Creation**: CRIU recreate the socket using the original family, type, and protocol.
2. **Address Binding**:
* CRIU creates a temporary "yard" (a `tmpfs` mount) to safely recreate socket files without interfering with the host filesystem.
* It creates the required directory structure and uses symlinks to ensure the `bind()` call targets the correct path.
3. **Peer Connection**: For connected stream sockets, one peer performs a `bind()` and `listen()`, while the other calls `connect()`. CRIU's file restoration engine coordinates this to ensure the server end is ready before the client attempts to connect.
4. **State and Data Injection**: Socket options and pending data are restored.
5. **Descriptor Redelivery**: In-flight file descriptors are re-injected into the socket's queue using the `SCM_RIGHTS` mechanism, ensuring the application receives them upon resumption.
## External Unix Sockets
If a socket is connected to a process *outside* the tree being checkpointed, CRIU cannot capture the peer's state. These are **External Sockets**.
* Restoration will fail by default for these sockets to prevent inconsistent states.
* Users can explicitly allow these connections using the `--external unix[ID]` option, which tells CRIU to treat the socket as a persistent external dependency.
**Userfaultfd** is a powerful Linux kernel feature that allows a userspace process (a "monitor") to handle page faults for other processes. CRIU leverages this feature to implement **Lazy Migration**, which significantly reduces the initial downtime when migrating memory-intensive applications.
## Lazy Migration Overview
In a traditional migration, the destination host must receive the entire memory dump (potentially many gigabytes) before the application can resume. This "freeze time" can be several seconds or even minutes for large applications.
With **Lazy Migration**:
1. CRIU captures only the minimal process state (registers, file descriptors, etc.) and essential memory pages.
2. The process tree is resumed immediately on the destination host with most of its memory regions mapped but empty.
3. Memory pages are transferred from the source host only when the application actually tries to access them ("on-demand").
## How it Works: The Lazy Pages Daemon
CRIU implements lazy migration through a dedicated background process called the **Lazy Pages Daemon**.
### 1. The Handover
During the restoration process, each process in the tree:
* Opens a `userfaultfd` file descriptor.
* Registers its memory regions with the kernel for tracking.
* Sends the descriptor to the Lazy Pages Daemon via a Unix domain socket using the `SCM_RIGHTS` mechanism.
* Resumes execution of the application code via `sigreturn`.
### 2. Handling Page Faults
When the application accesses a page that hasn't been loaded yet, the kernel pauses the faulting thread and sends a message to the Lazy Pages Daemon.
1. **Notification**: The daemon receives a `UFFD_EVENT_PAGEFAULT` message containing the faulting address.
2. **Retrieval**: The daemon fetches the required page contents, either from the local `pages.img` images or from a remote **Page Server** on the source host.
3. **Injection**: The daemon uses the `UFFDIO_COPY` (to fill data) or `UFFDIO_ZEROPAGE` (to fill zeros) ioctl to inject the page into the application's address space.
4. **Resumption**: Once the kernel confirms the page is filled, it automatically resumes the paused thread.
## Advanced Features: Non-Cooperative UFFD
CRIU utilizes "non-cooperative" kernel features to maintain consistency if the application modifies its memory layout while being lazily restored:
* **UFFD_FEATURE_EVENT_FORK**: If the process calls `fork()`, the kernel notifies the daemon, which then begins monitoring the new child process.
* **UFFD_FEATURE_EVENT_REMAP**: If the process moves memory using `mremap()`, the daemon updates its internal mapping table to ensure it continues to fetch the correct data for the new addresses.
* **UFFD_FEATURE_EVENT_UNMAP / REMOVE**: Handles scenarios where the application releases memory.
## Benefits and Trade-offs
* **Reduced Downtime**: Applications resume in milliseconds, regardless of their total memory size.
* **Network Jitter**: The application may experience minor stalls (latency spikes) during the initial phase as pages are fetched over the network.
* **Source Dependency**: The source host and the Page Server must remain alive and connected until the entire memory state has been successfully transferred to the destination.
## See also
* [Memory Dumping and Restoring](memory-dumping-and-restoring.md)
CRIU can verify that regular files and shared libraries being restored on the destination host are identical to the ones captured during the checkpoint. This is a critical security and stability feature, as mismatching libraries (e.g., a different version of `libc.so`) can lead to immediate application crashes or subtle data corruption due to changed offsets and symbols.
## How File Validation Works
File validation is managed via the `--file-validation` option. CRIU automatically captures metadata for all regular, file-backed mappings during the dump and stores it in the image files.
### Supported Validation Methods
CRIU supports two primary methods for validating files:
#### 1. Build-ID (Default)
Most modern Linux executables and shared libraries include a **GNU Build-ID**—a unique, compiler-generated hash stored in a dedicated ELF note section (`NT_GNU_BUILD_ID`).
* **Dumping**: CRIU identifies ELF files by checking their magic numbers. For each ELF file, it maps at most the first **1 MB** of the file (defined as `BUILD_ID_MAP_SIZE`) and extracts the Build-ID hash.
* **Restoring**: During restoration, CRIU performs the same extraction on the file residing on the target host. If the resulting hash does not match the one stored in the image, CRIU aborts the restoration to prevent corruption.
* **Fallback**: If a file is not an ELF or lacks a Build-ID, CRIU automatically falls back to validating the file by its size.
#### 2. File Size (`filesize`)
A simpler and faster validation method that only compares the total size of the file in bytes.
* **Advantage**: Minimal overhead as it only requires a `stat()` call.
* **Disadvantage**: Less reliable than Build-ID, as different versions of a file can occasionally have identical sizes.
## Usage and Configuration
File validation is enabled by default using the `buildid` method. You can explicitly configure the behavior using the `--file-validation` flag:
```bash
# Explicitly use Build-ID validation
criu restore --file-validation buildid ...
# Use only file size validation
criu restore --file-validation filesize ...
```
## Security and Integrity
File validation ensures that the restored process tree runs against the same binary environment it was captured in. This prevents "library injection" scenarios where an attacker might try to force a restored process to run against malicious versions of its original dependencies. It also ensures that internal pointers (such as function addresses) remain valid, as they are often tied to specific library versions.
The **vDSO** (virtual Dynamic Shared Object) and **VVAR** (virtual VARiable) areas are specialized memory regions mapped by the Linux kernel into every process. They enable high-performance userspace execution of specific system calls (such as `gettimeofday()` or `clock_gettime()`) by providing direct access to kernel-maintained code and data without the overhead of a full context switch.
## The Challenge of C/R
The vDSO is uniquely challenging for checkpoint/restore because its contents and memory layout are determined by the **host kernel**.
1. **Address Dependencies**: Applications frequently cache the addresses of vDSO functions. These must remain identical after restoration.
2. **ABI and Kernel Compatibility**: If a process is migrated to a different kernel version, the vDSO code from the original host might be incompatible with the new host's internal kernel-to-userspace data interfaces.
## CRIU's Restoration Strategy
CRIU uses two primary strategies to handle vDSO migration, automatically selecting the best one based on kernel capabilities detected during the [Kerndat](kerndat.md) phase.
### 1. The Proxy (Patching) Method
This is the fallback approach used when the kernel does not support mapping the vDSO at an arbitrary address:
* **Checkpoint**: CRIU captures the original vDSO contents and parses its ELF symbol table to identify the offsets of essential functions (e.g., `__vdso_gettimeofday`, `__vdso_time`).
* **Restoration**:
1. CRIU maps the original vDSO binary at its original virtual address.
2. It identifies the **new vDSO** provided by the current host kernel.
3. For each essential symbol, CRIU locates the corresponding function in the new vDSO.
4. CRIU **patches** the code in the original vDSO with a "trampoline" (a small jump instruction) that redirects execution to the equivalent function in the new host's vDSO.
* **Result**: The application continues to call the memory addresses it originally linked against, but it transparently executes the code optimized for the current host kernel.
### 2. The `arch_prctl` Method (Modern)
On modern kernels (v4.18+ for x86_64), CRIU uses a significantly more efficient mechanism:
* CRIU uses the `arch_prctl()` system call with the `ARCH_MAP_VDSO_64` (or `ARCH_MAP_VDSO_32`) flag to instruct the kernel to map its **current, native** vDSO directly at the application's original virtual address.
* **Advantage**: This eliminates the complexity of ELF patching and ensures the application always uses the most optimal, native code path for the host kernel.
## VVAR Handling
The **VVAR** area contains the raw data (such as the current clock value) that the vDSO code reads.
* VVAR is a data-only region and is not executable.
* CRIU identifies the VVAR mapping during the dump and ensures it is correctly re-established on the destination host, usually adjacent to the restored vDSO.
* When using the `arch_prctl` method, the kernel automatically manages the associated VVAR mapping when the vDSO is moved.
CRIU supports checkpointing and restoring **zombie processes** (tasks that have terminated but have not yet been reaped by their parent). These processes are a vital part of a process tree's state, as they maintain exit codes that the parent may eventually need to read.
## How CRIU Handles Zombies
Zombie processes are unique because they have no active memory, no file descriptors, and no CPU state. However, they still occupy an entry in the kernel's process table and maintain an identity via their PID.
### 1. Checkpointing (Dumping)
During the dump phase, CRIU identifies zombie tasks by checking their state in `/proc/$pid/stat`.
* **State Capture**: CRIU records the zombie's PID and its original **exit code**.
* **Minimal Footprint**: Because zombies have no address space, CRIU does not attempt to inject parasite code or dump memory for them.
### 2. Restoration
Restoring a zombie process involves recreating a task and immediately forcing it into a terminated state without allowing its parent to reap it.
* **The Helper Technique**: CRIU forks a new process using the original PID (via `clone3` or `ns_last_pid`).
* **Immediate Termination**: This process immediately calls the `exit()` system call with the captured exit code.
* **Parent Coordination**: The parent process of the zombie (which is also being restored) is managed to ensure it does not accidentally reap the new zombie before the restoration is complete.
* **Result**: This leaves the new process in the zombie state, perfectly matching the original environment's PID table.
- [A simple example of usage](http://criu.org/Simple_loop)
- [More sophisticated example with graphical app](http://criu.org/VNC)
- [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/index.php?title=FAQ)